maltadirk 发表于 2021-4-1 21:09

unity 无限滚动列表

小工具,留着备用~
实现思路:
1.生成列表之前将所有数据准备好,放入List中,content的高度在初始化时根据数据长度设置好。
2.滚动时取索引区间的数据,有几个索引就显示几行item。
3.滚动列表只负责显示,每个item上的内容由调用者控制:SetItemInfo(Transform item, int index)。

效果:

QQ录屏20210401112927.mp4_1617247824.gif



调用方式:
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;/*    des:循环列表测试    author:lfw*/public class TestPanel : MonoBehaviour{      InfinityScrollList m_scrollList;                  //无限滚动列表      List<string> m_dataList = new List<string>(100);    //准备好的数据      public override void Awake()      {                      var scroll = Transform.Find("Scroll View").GetComponent<ScrollRect>();            var item = ObjectManager.Instance.InstantiateObject("Assets/Res/Prefabs/Item.prefab");            for(int i = 0; i < 20; i++)                m_dataList.Add("数据" + i);            m_scrollList = new Util.InfinityScrollList(scroll);            m_scrollList.Init(item, 6, m_dataList.Count, SetItemInfo);    //初始化      }      //自定义填充函数      private void SetItemInfo(Transform item, int index)      {            item.Find("Text").GetComponent<Text>().text = m_dataList;            //var btn = item.transform.Find("Button").GetComponent<Button>();            //btn.onClick.RemoveAllListeners();            //btn.onClick.AddListener(            //    () =>            //    {            //      m_dataList.RemoveAt(index);            //      m_scrollList.DataCount -= 1;            //      m_scrollList.DoForceUpdate(false);            //    });      }}
代码实现:
InfinityScrollList .cs
using System;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;/*    des:循环列表类    author:lfw*/class InfinityScrollList{      int m_headIndex = 0;                                  //顶部显示的数据索引      int m_tailIndex = 0;                                  //最底部显示数据索引      float m_itemHeight = 0;                               //item高度      float m_topPading = 0;                              //距顶部边距      float m_spacing = 0;                                  //行间距      int m_maxItemCount;                                 //最大item数量(最好总高度刚好超过滚动框高度)                Action<Transform, int> m_setInfoCallback;             //给每个item设置显示内容的函数      List<Transform> m_itemList = new List<Transform>();   //item列表      GameObject m_itemPrefab;      ScrollRect m_scrollView;      Transform m_content;      RectTransform m_contentRect;      public int DataCount { get; set; } = 0;                //待填充数据数量            public InfinityScrollList(ScrollRect scrollView)      {            m_headIndex = 0;            m_tailIndex = 0;            m_scrollView = scrollView;            m_content = scrollView.content;            m_contentRect = m_content.GetComponent<RectTransform>();            m_scrollView.onValueChanged.AddListener(this.OnValueChanged);      }      /// <summary>      /// 初始化必要数据      /// </summary>      /// <param name="itemPrefab">item预制体</param>      /// <param name="maxItem">最大item数量</param>      /// <param name="maxData">数据数量</param>      /// <param name="SetItemCallBack">修改item信息的回调</param>      public void Init(GameObject itemPrefab, int maxItem, int maxData, Action<Transform, int> setItemCallback = null)      {            m_itemPrefab = itemPrefab;            m_headIndex = 0;            m_tailIndex = 0;            m_maxItemCount = maxItem;            DataCount = maxData;            m_setInfoCallback = setItemCallback;            m_itemHeight = itemPrefab.GetComponent<RectTransform>().rect.height + m_spacing;            m_contentRect.sizeDelta = new Vector2(m_contentRect.sizeDelta.x, m_itemHeight * DataCount + m_topPading);            UpdateContent();      }      /// <summary>      /// 数据发生变化时刷新item显示内容      /// </summary>      /// <param name="toTop"> 是否回到顶部</param>      public void DoForceUpdate(bool toTop)      {            if (toTop)            {                m_headIndex = 0;            }            UpdateContent();      }      /// <summary>      /// 根据首尾数据索引,刷新item内容      /// </summary>      private void UpdateContent()      {            for (int i = 0; i < m_itemList.Count; i++)            {                if (i >= DataCount)                  m_itemList.gameObject.SetActive(false);            }            int itemCount = Mathf.Clamp(DataCount, 0, m_maxItemCount);                        Transform tran;            for (Int32 i = 0; i < itemCount; i++)            {                if (i < m_itemList.Count)                {                  tran = m_itemList;                }                else                {                  var item = m_itemPrefab.Instantiate();                  tran = item.transform;                  tran.GetComponent<RectTransform>().anchorMin = new Vector2(0.5f, 1);                  tran.GetComponent<RectTransform>().anchorMax = new Vector2(0.5f, 1);                  tran.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1);                  tran.SetParent(m_content, false);                  m_itemList.Add(tran);                }                int index = m_headIndex + i;                tran.name = index.ToString();                tran.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -m_itemHeight * index - m_topPading);                m_setInfoCallback?.Invoke(tran, index); //更新内容            }            m_tailIndex = m_headIndex + (itemCount - 1);            m_contentRect.sizeDelta = new Vector2(m_contentRect.sizeDelta.x, m_itemHeight * DataCount + m_topPading);      }      private void OnValueChanged(Vector2 v2)      {            if (m_itemList.Count <= 0)            {                return;            }            //向上滚动            while (m_contentRect.anchoredPosition.y > (m_headIndex + 1) * m_itemHeight && m_tailIndex != DataCount - 1)            {                Transform _first = m_itemList;                RectTransform _firstRect = _first.GetComponent<RectTransform>();                //将顶部item移到底部                m_itemList.RemoveAt(0);                m_itemList.Add(_first);                m_headIndex++;                m_tailIndex++;                _firstRect.anchoredPosition = new Vector2(0, -m_tailIndex * m_itemHeight - m_topPading);                //修改显示                _first.name = m_tailIndex.ToString();                m_setInfoCallback?.Invoke(_first, m_tailIndex);            }            //向下滚动            while (m_contentRect.anchoredPosition.y < m_headIndex * m_itemHeight && m_headIndex != 0)            {                Transform _last = m_itemList;                RectTransform _lastRect = _last.GetComponent<RectTransform>();                m_itemList.RemoveAt(m_itemList.Count - 1);                m_itemList.Insert(0, _last);                m_headIndex--;                m_tailIndex--;                _lastRect.anchoredPosition = new Vector2(0, -m_headIndex * m_itemHeight - m_topPading);                _last.name = m_headIndex.ToString();                m_setInfoCallback?.Invoke(_last, m_headIndex);            }      }    }
页: [1]
查看完整版本: unity 无限滚动列表