4.unity UI ScrollRect 无限滚动条(最详细)

本文详细介绍了在Unity中使用ScrollRect实现无限滚动数据的处理方式,特别是针对商店商品、排行榜等大量数据场景。通过InfinityGridLayoutGroup类实现循环滚动,并提供了删除和刷新功能。MarketLayoutGroup作为数据管理器,负责在滑动时为每个数据对象赋值。MarketElement类作为UI对象的基类,提供设置数据的方法。示例中还包括ElementMarket的实现,可以根据具体项目的数据结构进行调整。

 在游戏开发中 经常遇到滚动显示的数据 特别是商店商品 排行榜 .......等 数据很多,每一条数据去加载一个UI来显示显然对内存浪费很大,这种情况处理一般就是用几个显示条可滚动循环显示无限数据条。本篇介绍实现过程和大体思路以及可重用的滑动脚本InfinityGridLayoutGroup和MarketLayoutGroup数据管理刷新脚本。MarketElement类要看具体项目中具体数据结构来设计;仅供产考。

一 .总体流程:

  建一个循环滑动脚本 InfinityGridLayoutGroup类并且有删除刷新功能;

  一个数据管理刷新脚本如:MarketLayoutGroup(商店市场数据刷新管理器),继承InfinityGridLayoutGroup类 并且在滑动   的时候给每条数据对象赋值显示;

  一个单数据对象MarketElement;

  一个UI 用于显示滑动;

1 .InfinityGridLayoutGroup类:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;

[RequireComponent(typeof(GridLayoutGroup))]
[RequireComponent(typeof(ContentSizeFitter))]
public class InfinityGridLayoutGroup : MonoBehaviour
{

    public int minAmount = 0;//实现无限滚动,需要的最少的child数量。屏幕上能看到的+一行看不到的,比如我在屏幕上能看到 2 行,每一行 2 个。则这个值为 2行*2个 + 1 行* 2个 = 6个。  
    public bool changePanel = false;//切换面板
    public bool up = false;
    RectTransform rectTransform;

    GridLayoutGroup gridLayoutGroup;
    ContentSizeFitter contentSizeFitter;

    ScrollRect scrollRect;

    List<RectTransform> children = new List<RectTransform>();

    Vector2 startPosition;

    public int amount = 0;

    public delegate void UpdateChildrenCallbackDelegate(int index, Transform trans);
    public UpdateChildrenCallbackDelegate updateChildrenCallback = null;

    public int realIndex = -1;
    int realIndexUp = -1; //从下往上;  
    #region // 改动
    Vector2 gridLayoutSizeLast;
    Vector2 gridLayoutPosLast;
    Vector2 currentPos;
    #endregion
    public bool hasInit = false;
    Vector2 gridLayoutSize;
    Vector2 gridLayoutPos;
    Dictionary<Transform, Vector2> childsAnchoredPosition = new Dictionary<Transform, Vector2>();
    Dictionary<Transform, int> childsSiblingIndex = new Dictionary<Transform, int>();

    // Use this for initialization  
    void Start()
    {
        StartCoroutine(InitChildren());
    }

    IEnumerator InitChildren()
    {
        yield return 0;
        // Debug.Log("hasInit" + hasInit);
        minAmount = transform.childCount;
        if (!hasInit)
        {
            //childsAnchoredPosition.Clear();
            //获取Grid的宽度;  
            rectTransform = GetComponent<RectTransform>();

            gridLayoutGroup = GetComponent<GridLayoutGroup>();
            gridLayoutGroup.enabled = false;
            contentSizeFitter = GetComponent<ContentSizeFitter>();
            contentSizeFitter.enabled = false;
            gridLayoutSizeLast = rectTransform.sizeDelta;
            gridLayoutPos = rectTransform.anchoredPosition;
            gridLayoutSize = rectTransform.sizeDelta;

            // Debug.Log("<Color=Red>children</Color>---" + children.Count + "realIndex---" + realIndex);
            //注册ScrollRect滚动回调;  
            scrollRect = transform.parent.GetComponent<ScrollRect>();
            scrollRect.onValueChanged.AddListener((data) => { ScrollCallback(data); });

            //获取所有child anchoredPosition 以及 SiblingIndex;  
            for (int index = 0; index < transform.childCount; index++)
            {
                Transform child = transform.GetChild(index);
                RectTransform childRectTrans = child.GetComponent<RectTransform>();
                childsAnchoredPosition.Add(child, childRectTrans.anchoredPosition);

                childsSiblingIndex.Add(child, child.GetSiblingIndex());
            }
            //Debug.Log("<Color=Blue>children</Color>---" + children.Count + "realIndex---" + realIndex);
        }
        else
        {
            //Debug.Log("gridLayoutPosLast--" + gridLayoutSizeLast.y);
            rectTransform.anchoredPosition = new Vector2(gridLayoutPos.x, Vector2.zero.y);
            // Debug.Log("current--" + currentPos.y);

            rectTransform.sizeDelta = gridLayoutSize;
            gridLayoutSizeLast = rectTransform.sizeDelta;
            // Debug.Log("rectTransform.sizeDelta--" + rectTransform.sizeDelta.y);

            children.Clear();

            realIndex = -1;
            realIndexUp = -1;

            //children重新设置上下顺序;  
            foreach (var info in childsSiblingIndex)
            {
                info.Key.SetSiblingIndex(info.Value);
            }

            //children重新设置anchoredPosition;  
            for (int index = 0; index < transform.childCount; index++)
            {
                Transform child = transform.GetChild(index);

                RectTransform childRectTrans = child.GetComponent<RectTransform>();
                if (childsAnchoredPosition.ContainsKey(child))
                {
                    childRectTrans.anchoredPosition = childsAnchoredPosition[child];
                }
                else
                {
                    Debug.LogError("childsAnchoredPosition no contain " + child.name);
                }
            }
        }

        //获取所有child;  
        for (int index = 0; index < transform.childCount; index++)
        {
            Transform trans = transform.GetChild(index);
            trans.gameObject.SetActive(true);

            children.Add(transform.GetChild(index).GetComponent<RectTransform>());

            //初始化前面几个;  
            UpdateChildrenCallback(children.Count - 1, transform.GetChild(index));
        }

        startPosition = rectTransform.anchoredPosition;
        // Debug.Log("<Color=Red>children</Color>---"+ children.Count+ "realIndex---"+ realIndex);
        realIndex = children.Count - 1;

        ShowElement(realIndex);
        //Debug.Log( scrollRect.transform.TransformPoint(Vector3.zero));  

        // Debug.Log(transform.TransformPoint(children[0].localPosition));  

        hasIni
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值