简单优化滑动列表

优化滑动列表

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScrollList : MonoBehaviour
{
    [SerializeField] ScrollRect scrollRect;//滑动组件
    [SerializeField] RectTransform elemParent;//元素父对象
    [SerializeField] RectTransform elem;//元素
    [SerializeField] RectTransform viewPort;//视口

    int count = 1000;//元素总数
    int defaultCreateCount = 6;//默认创建的元素数量

    float visiableAreaHeight;//可视区域的高度
    float visiableAreaWidth;//可视区域的宽度
    Vector2 elemSize;//单个元素的宽高

    Dictionary<int, ListElement> elemDic = new Dictionary<int, ListElement>();//记录可视区域内的元素

    List<ListElement> notUsedElemList = new List<ListElement>() { Capacity = 1000 };//缓存区

    private void Start()
    {
        visiableAreaHeight = viewPort.sizeDelta.y;
        visiableAreaWidth = viewPort.sizeDelta.x;
        elemSize = elem.sizeDelta;

        var totalRow = Mathf.CeilToInt(count / 2.0f);//2是每行的元素数量
        var totalHeight = elemSize.y * totalRow;
        elemParent.sizeDelta = new Vector2(visiableAreaWidth, totalHeight);//设置content大小

        for (int i = 0; i < defaultCreateCount; i++)//默认创建
        {
            RectTransform obj = Instantiate(elem, elemParent);
            var listElem = obj.GetComponent<ListElement>();
            listElem.ShowContent(i.ToString());
            obj.anchoredPosition = SetElemPos(i);
            elemDic.Add(i, listElem);
        }
        scrollRect.onValueChanged.AddListener(ChangeValue);//添加事件
    }


    Vector2 SetElemPos(int index)//根据索引设置元素位置
    {
        int x = index / 2;//2是每行的元素数量
        int y = index % 2;//2是每行的元素数量
        return new Vector2(y * elemSize.y, -x * elemSize.x);
    }


    void ChangeValue(Vector2 value)
    {
        var visiableAreaTop = elemParent.anchoredPosition.y;//conten可见部分在视口上的顶部位置
        var visiableAreaBottom = visiableAreaTop + visiableAreaHeight;//conten可见部分在视口上的底部位置

        int beginIndex = (int)(visiableAreaTop / elemSize.y) * 2;//获取 可见content区域开始元素的索引
        int endIndex = (int)(visiableAreaBottom / elemSize.y) * 2 + 1;//获取 可见content区域结束元素的索引

        //不在视野范围内的元素 移出字典
        for (int i = 0; i < beginIndex; i++)
        {
            if (elemDic.ContainsKey(i))
            {
                var listElem = elemDic[i];
                elemDic.Remove(i);
                notUsedElemList.Add(listElem);
            }
        }
        for (int i = endIndex + 1; i < count; i++)
        {
            if (elemDic.ContainsKey(i))
            {
                var listElem = elemDic[i];
                elemDic.Remove(i);
                notUsedElemList.Add(listElem);
            }
        }
        //视野范围内的元素
        for (int i = beginIndex; i <= endIndex; i++)
        {
            if (i < count && i >= 0)
            {
                if (elemDic.ContainsKey(i))
                {
                    var listElem = elemDic[i];
                    listElem.ShowContent(i.ToString());
                }
                else
                {
                    if (notUsedElemList.Count > 0)
                    {
                        var temp = notUsedElemList[0];
                        (temp.transform as RectTransform).anchoredPosition = SetElemPos(i);
                        temp.ShowContent(i.ToString());
                        elemDic.Add(i, temp);
                        notUsedElemList.RemoveAt(0);
                    }
                    else
                    {
                        RectTransform obj = Instantiate(elem, elemParent);
                        obj.anchoredPosition = SetElemPos(i);
                        var listElem = obj.GetComponent<ListElement>();
                        listElem.ShowContent(i.ToString());
                        elemDic.Add(i, listElem);
                    }
                }
            }
        }
    }
}

元素

using UnityEngine;
using UnityEngine.UI;
public class ListElement : MonoBehaviour
{
    [SerializeField] Text content;
    public void ShowContent(string info)
    {
        content.text = info;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值