Unity Scrollview displays large amounts of data

Time:2022-5-28

Original link:https://www.cnblogs.com/jingjiangtao/p/15827823.html

problem

Unity’s Scrollview can display a list in the form of a Scrollview. However, when there is a lot of data in the list, it will get stuck when it is displayed once with Scrollview, and the speed of generating the list will slow down.

To solve this problem, you can only display the visible data items, and the invisible data items will not be loaded. When sliding the list, the data items will be updated in real time. In this way, you only need to create and update the visible data items, and loading and sliding will not get stuck.

This article only implements the vertical scrolling list.Other forms of list implementation are similar.

Implementation method

To implement a common scrolling view list, there are two code structures to choose from: interfaces and delegates. The implementation method of interface is more traditional, and the implementation method of delegation is more flexible.

This article chooses to use interfaces. If you want to use delegates, you can change the methods defined in all interfaces into delegates at the corresponding positions.

Set up UI

New Scrollview

First, you need to build the Scrollview UI for testing. Create a new scene. If there is no canvas in the scene, create a new one, and then create a new scroll view under the canvas.

 

The next step is to make some changes to the listImportant settings:

1.Select the object where the scrollrect component is located, uncheck horizontal to disable horizontal scrolling, and set scroll sensitivity to 50 to make the mouse wheel slide more sensitive.

 

2.Select the content object, and first set the anchor point and size of the content object to be as large as the viewport. Specifically, click the anchor point setting tool of the recttransform component of the content object,Press alt, select the layout in the diagram:

 

In this way, the content is as large as the viewport

3.Select the content object again, and click the recttransform component anchor setting tool of the content object,Hold shift, select the layout in the diagram:

 

In this way, the position of content can be obtained through the posy value of content. Finally, put a picture of the recttransform component value of content:

 

New list item

Next, you need to create a list item to display the data in the list. For simplicity, a list item only contains a text indicating the number of the list item and a delete button.

1.Select content, right-click content, create an empty object, rename it textitem, and adjust the empty object to the appropriate size:

  

 

2.Make some important settings for the list items: select textitem, click the anchor tool of recttransform component,Hold shift, select the layout in the diagram:

 

This is the value of the recttransform component after setting:

 

3.Add text and buttons to textitem:

 

4.Create a new prefabs directory under the assets directory, drag the textitem object to this directory to make a prefab, and then delete the textitem under the content:

 

5.Create a new button named addbtn under canvas, as shown in the figure, to realize the function of adding list items:

 

So far, the UI for testing has been set up.

code implementation

The class loopscrollitem CS

This class is used to save the data in a single list item. It needs to be initialized with the GameObject of the list item. In this example, the data of the list item only has its own recttransform and GameObject. If you want to add new data, you can directly expose it in this class for easy access.

namespace LoopScrollTest.LoopScroll
{
    public class LoopScrollItem
    {
        public RectTransform RectTransform => _transform;

        private RectTransform _transform;
        private GameObject _gameObject;

        public LoopScrollItem(GameObject gameObject)
        {
            _gameObject = gameObject;
            _transform = _gameObject.transform as RectTransform;
        }
    }
}

 

Interface for Scrollview script calls iloopscrollview CS

The interface for scrolling lists contains several operations on lists. If there are other operations, they can be declared in the interface and called in loopscrollview.

 

namespace LoopScrollTest.LoopScroll
{
    public interface ILoopScrollView
    {
        /// 
        ///Updates the given list item with the data at the given index
        /// 
        void UpdateItemContent(int index, LoopScrollItem item);

        /// 
        ///Generates a list item from the data at the given index and returns
        /// 
        GameObject InitScrollViewList(int index);

        /// 
        ///Generate a new list item and return
        /// 
        GameObject InitOneItem();

        /// 
        ///Delete the specified list item
        /// 
        void DeleteOneItem(Transform item);

        /// 
        ///Process all other list items after deleting one list item
        /// 
        void OtherItemAfterDeleteOne(LoopScrollItem item);
    }
}

 

The script that controls the Scrollview loopscrollview CS

The main class of the scrolling view, which inherits monobehavior,And you need to hang it on the same object as the scrollrect component, and drag the scrollrect component to the reference slot. This class handles all operations on the scrolling view and calls methods in the interface.

namespace LoopScrollTest.LoopScroll
{
    [RequireComponent(typeof(ScrollRect))]
    public class LoopScrollView : MonoBehaviour
    {
        public ScrollRect scrollRect;

        //List item array
        protected List _items = new List();
        protected float _itemHeight;
        protected int _visibleCount;
        protected float _visibleHeight;
        protected int _sourceListCount;

        //An instance of the list operation interface type needs to be assigned during initialization
        protected ILoopScrollView _scrollViewOperate;

        protected virtual void Update()
        {
            RefreshGestureScrollView();
        }

        /// 
        ///Initializes the values and references of a circular list
        /// 
        public virtual void InitScrollView(float itemHeight, ILoopScrollView scrollViewOperate)
        {
            _itemHeight = itemHeight;
            _visibleHeight = (scrollRect.transform as RectTransform).rect.height;
            _visibleCount = (int)(_visibleHeight / _itemHeight) + 1;

            _scrollViewOperate = scrollViewOperate;
        }

        /// 
        ///Initializing the data source of a circular list
        /// 
        public virtual void InitScrollViewList(int sourceListCount)
        {
            _sourceListCount = sourceListCount;
            int generateCount = ResizeContent();
            scrollRect.content.anchoredPosition = Vector2.zero;
            _items.Clear();

            for (int i = 0; i < generateCount; i++)
            {
                GameObject itemGameObject = _scrollViewOperate.InitScrollViewList(i);
                LoopScrollItem item = new LoopScrollItem(itemGameObject);
                float itemY = -i * _itemHeight;
                item.RectTransform.anchoredPosition =
                    new Vector2(scrollRect.content.anchoredPosition.x, itemY);

                _items.Add(item);
            }
        }

        /// 
        ///Align the items of the specified index to the top of the list interface
        /// 
        public virtual void MoveIndexToTop(int index)
        {
            float contentY = index * _itemHeight;
            scrollRect.content.anchoredPosition =
                new Vector2(scrollRect.content.anchoredPosition.x, contentY);

            RefreshGestureScrollView();
        }

        /// 
        ///Align the items of the specified index to the bottom of the list interface
        /// 
        public virtual void MoveIndexToBottom(int index)
        {
            float contentY = (index + 1) * _itemHeight - _visibleHeight;
            contentY = contentY < 0 ? 0f : contentY;
            scrollRect.content.anchoredPosition =
                new Vector2(scrollRect.content.anchoredPosition.x, contentY);

            RefreshGestureScrollView();
        }

        /// 
        ///Judge whether the specified index needs to be focused to the bottom, and align if necessary
        /// 
        public virtual void MoveToBottomIfNeeded(int index)
        {
            float itemY = -(index + 1) * _itemHeight;
            float bottomY = -(scrollRect.content.anchoredPosition.y + _visibleHeight);

            if (itemY < bottomY)
            {
                MoveIndexToBottom(index);
            }
        }

        /// 
        ///Add a new item to the list
        /// 
        public virtual void AddOneItem()
        {
            _sourceListCount++;
            int generateCount = ResizeContent();

            if (_items.Count < generateCount)
            {
                GameObject itemGameObject = _scrollViewOperate.InitOneItem();
                LoopScrollItem item = new LoopScrollItem(itemGameObject);
                _items.Add(item);
            }

            RefreshGestureScrollView();
        }

        /// 
        ///Delete a list item
        /// 
        public virtual void DeleteOneItem()
        {
            _sourceListCount--;
            int generateCount = ResizeContent();
            if (generateCount < _items.Count)
            {
                int lastIndex = _items.Count - 1;
                _scrollViewOperate.DeleteOneItem(_items[lastIndex].RectTransform);
                _items.RemoveAt(lastIndex);
            }

            RefreshGestureScrollView();

            foreach (LoopScrollItem item in _items)
            {
                _scrollViewOperate.OtherItemAfterDeleteOne(item);
            }
        }

        /// 
        ///Readjust the height of the content according to the number of current gesture items
        /// 
        protected virtual int ResizeContent()
        {
            int generateCount = Mathf.Min(_visibleCount, _sourceListCount);
            float contentHeight = _sourceListCount * _itemHeight;
            scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, contentHeight);
            return generateCount;
        }

        /// 
        ///Refresh list contents
        /// 
        protected virtual void RefreshGestureScrollView()
        {
            float contentY = scrollRect.content.anchoredPosition.y;
            int skipCount = (int)(contentY / _itemHeight);

            for (int i = 0; i < _items.Count; i++)
            {
                if (skipCount >= 0 && skipCount < _sourceListCount)
                {
                    _scrollViewOperate.UpdateItemContent(skipCount, _items[i]);

                    float itemY = -skipCount * _itemHeight;
                    _items[i].RectTransform.anchoredPosition =
                        new Vector2(scrollRect.content.anchoredPosition.x, itemY);

                    skipCount++;
                }
            }
        }
    }
}

 

 

The above script is all the code of the scrolling view. It can be used by attaching the required script and implementing the interface in other classes.

 

The following is an example of a call loop list:

Script textitem CS

The script inherits monobehavior,You need to hang it on the textitem prefab and drag text and button to the reference fieldTo control the behavior of individual list items.

namespace LoopScrollTest
{
    public class TextItem : MonoBehaviour
    {
        public Text text;
        public Button deleteBtn;

        public SourceData Data => _sourceData;

        private Action _deleteItemAction;
        private SourceData _sourceData;

        private void Awake()
        {
            deleteBtn.onClick.AddListener(OnClickDelete);
        }

        /// 
        ///Delegate to initialize data and button clicks
        /// 
        public void Init(SourceData data, Action deleteItemAction)
        {
            _sourceData = data;
            _deleteItemAction = deleteItemAction;

            text.text = _sourceData.text;
        }

        /// 
        ///Update referenced source data
        /// 
        public void UpdateSourceData(SourceData data)
        {
            _sourceData = data;
            text.text = _sourceData.text;
        }

        /// 
        ///Delete button click event
        /// 
        private void OnClickDelete()
        {
            _deleteItemAction?.Invoke(this);
        }
    }
}

 

 

Data source entity class

namespace LoopScrollTest
{
    public class SourceData
    {
        //Data content
        public string text;
    }
}

 

Call the script testloopscrollview CS

The script used to control the UI and call the circular list needs to create a new GameObject object in the scene and drag the corresponding reference to the reference slot to assign a value.

namespace LoopScrollTest
{
    public class TestLoopScrollView : MonoBehaviour, ILoopScrollView
    {
        [tooltip ("the number of source data lists that need to be re run to take effect after modification")]
        public uint count = 300;

        //Reference to scrolling list
        public LoopScrollView loopScrollView;

        //Reference to add button
        public Button addBtn;

        //Reference to the content object of Scrollview
        public RectTransform content;

        //Reference to a single list item prefab
        public TextItem textItemPrefab;

        //Source data list
        private List _sourceList = new List();
        private int nextId = 1;

        private void Awake()
        {
            addBtn.onClick.AddListener(OnClickAddItem);

            //Gets the height of a single list item
            float itemHeight = (textItemPrefab.transform as RectTransform).rect.height;
            //Initializing references in a scrolling list
            loopScrollView.InitScrollView(itemHeight, this);
        }

        private void Start()
        {
            //Initialize the source data list as the data source of the list
            for (int i = 0; i < count; i++)
            {
                SourceData data = new SourceData
                {
                    text = nextId.ToString()
                };

                _sourceList.Add(data);

                nextId++;
            }

            //Initialize the display of the scrolling list
            loopScrollView.InitScrollViewList(_sourceList.Count);
        }

        /// 
        ///Append a new item to the list
        /// 
        private void OnClickAddItem()
        {
            SourceData data = new SourceData
            {
                text = nextId.ToString(),
            };

            _sourceList.Add(data);
            nextId++;

            loopScrollView.AddOneItem();
            loopScrollView.MoveIndexToBottom(_sourceList.Count - 1);
        }

        /// 
        ///Generate a single list item based on the given source data
        /// 
        private TextItem InitTextItem(SourceData sourceData)
        {
            TextItem item = Instantiate(textItemPrefab, content);
            item.Init(sourceData, DeleteItemAction);
            return item;
        }

        /// 
        ///Click the callback of the delete button of a single list item to delete a single list item
        /// 
        private void DeleteItemAction(TextItem item)
        {
            _sourceList.Remove(item.Data);
            loopScrollView.DeleteOneItem();
        }

        #Interface method implemented by Region

        public virtual void DeleteOneItem(Transform item)
        {
            DestroyImmediate(item.gameObject);
        }

        public virtual GameObject InitOneItem()
        {
            TextItem item = InitTextItem(_sourceList[_sourceList.Count - 1]);
            return item.gameObject;
        }

        public virtual GameObject InitScrollViewList(int index)
        {
            TextItem item = InitTextItem(_sourceList[index]);
            return item.gameObject;
        }

        public virtual void OtherItemAfterDeleteOne(LoopScrollItem item)
        {

        }

        public virtual void UpdateItemContent(int index, LoopScrollItem item)
        {
            //Update source data for list item references
            TextItem textItem = item.RectTransform.GetComponent();
            textItem.UpdateSourceData(_sourceList[index]);
        }

        #endregion
    }
}

 

 

effect

 

Complete project

https://github.com/jingjiangtao/LoopScrollView

reference

https://blog.csdn.net/lxt610/article/details/90036080

Recommended Today

Lasso of MATLAB generalized linear model GLM Poisson regression, regularization of elastic network, classification, prediction of test score data and visualization of cross validation

Original link:http://tecdat.cn/?p=24777  Building datasets with redundant predictors and usingLasso and GLMIdentify these predictors. applylassoRegularization to remove redundant prediction variables Create aXA random matrix containing 100 observations and 10 prediction variables.yOnly four predictive variables and a small amount of noise are used to create a normally distributed dependent variable. Default randn ; X* weight + randn*0.1; % […]