找回密码
 立即注册
查看: 523|回复: 0

unity 无限滚动列表

[复制链接]
发表于 2021-4-1 21:09 | 显示全部楼层 |阅读模式
小工具,留着备用~
实现思路:
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[index];            //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[0];                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[m_itemList.Count - 1];                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);            }        }    }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-20 20:21 , Processed in 0.090133 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表