无限滚动原理

无限滚动的原理:

就是通过固定数量的图片或者其他UI组件来实现不固定的数量的图片,具体的原理就是把图片的左下角与世界左上角的坐标进行对比计算,如果这个距离大于一个图片的长度,那就把这个图片从上面拿到下面来,并且重新加载图片

补充:开始写博客的时候只写了原理,最近因为工作需要,就把代码和工程上传了吧(可能不完善,但是能实现功能,有问题欢迎骚扰)
代码:

/*数据类*/
using System.Collections.Generic;

public class UIData
{
    private List<ItemData> itemList;

    public UIData()
    {
        itemList = new List<ItemData>();

        for (int i = 1; i < 101; i++)
        {
            ItemData item = new ItemData
            {
                data = i.ToString()
            };

            itemList.Add(item);
        }
    }

    /// <summary>
    /// 获取数据
    /// </summary>
    /// <returns></returns>
    public List<ItemData> GetData()
    {
        return itemList;
    }
}
public class ItemData
{
    public string data;
}
/*Item管理类*/
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class UIItem : MonoBehaviour
{
    private Button btn;
    private TextMeshProUGUI text;
    private ItemData itemData = null;
    private UIItemManager itemManager;

    /// <summary>
    /// 初始化Item
    /// </summary>
    /// <param name="manager"></param>
    /// <param name="data"></param>
    public void InitilItem(UIItemManager manager, ItemData data)
    {
        InitilUI();

        itemManager = manager;
        itemData = data;

        text.text = data.data;
    }

    /// <summary>
    /// 获取Item数据
    /// </summary>
    /// <returns></returns>
    public ItemData GetItemData()
    {
        return itemData;
    }

    /// <summary>
    /// 更新Item数据
    /// </summary>
    public void UpdateItemData(ItemData data)
    {
        InitilUI();
        itemData = data;
        if (text != null)
            text.text = data.data;
    }

    private void InitilUI()
    {
        btn = transform.Find("Button").GetComponent<Button>();
        text = btn.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
        btn.onClick.AddListener(BtnClicked);
    }

    private void BtnClicked()
    {
        itemManager.ItemBtnClicked(itemData);
    }
}
/*UI管理类*/
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class UIItemManager : MonoBehaviour
{
    public List<UIItem> itemList = new List<UIItem>();
    public List<ItemData> dataList = new List<ItemData>();

    private ScrollRect scroll;
    private Transform content;
    private RectTransform scrollRect;
    private GridLayoutGroup gridLayoutGroup;

    private int itemColumnCount;//列数
    private int itemRowCount;//行数

    private int dataIndex;
    private float scrollYMax;
    private float scrollYMin;
    private float itemHalfSize;


    private float curValue;
    private float lastValue;

    private void Awake()
    {
        UIData uiData = new UIData();
        dataList = uiData.GetData();
    }

    private void Start()
    {
        content = transform.Find("Viewport/Content");
        scroll = transform.GetComponent<ScrollRect>();
        scrollRect = scroll.GetComponent<RectTransform>();
        scrollRect = transform.GetComponent<RectTransform>();
        gridLayoutGroup = content.GetComponent<GridLayoutGroup>();

        if (itemList.Count <= 0)
        {
            for (int i = 0; i < content.childCount; i++)
            {
                itemList.Add(content.GetChild(i).GetComponent<UIItem>());
            }
        }

        itemColumnCount = CalculateColumnCount(scrollRect.rect.width, gridLayoutGroup.padding.left, gridLayoutGroup.padding.right, gridLayoutGroup.spacing.x, gridLayoutGroup.cellSize.x);
        itemRowCount = itemList.Count / itemColumnCount;

        scrollYMax = scrollRect.rect.yMax + scrollRect.rect.height;
        scrollYMin = scrollRect.rect.yMin + scrollRect.rect.height;
        itemHalfSize = gridLayoutGroup.cellSize.y / 2;

        scroll.onValueChanged.AddListener(OnValueChanged);

        InitilData(dataList);
    }

    /// <summary>
    /// 初始化数据
    /// </summary>
    public void InitilData(List<ItemData> list)
    {
        for (int i = 0; i < itemList.Count; i++)
        {
            itemList[i].InitilItem(this, dataList[i]);
        }
        dataIndex = itemList.Count;
    }

    /// <summary>
    /// 回调
    /// </summary>
    /// <param name="arg0"></param>
    private void OnValueChanged(Vector2 arg0)
    {
        curValue = arg0.y;

        if (lastValue != 0)
        {
            if (lastValue > curValue)
            {
                Debug.Log("下滑");
                for (int i = 0; i < itemRowCount; i++)
                {
                    int curIndex = i * itemColumnCount;
                    int nextIndex = (i + 1) * itemColumnCount;
                    nextIndex %= itemList.Count;

                    if (itemList[curIndex].transform.position.y - itemHalfSize > scrollYMax)
                    {
                        if (itemList[nextIndex].transform.position.y + itemHalfSize < scrollYMax)
                        {
                            UpdateItemsPos(VerticalType.Down, curIndex);
                        }
                    }
                }
            }
            if(lastValue <= curValue)
            {
                Debug.Log("上滑");
                for (int i = 0; i < itemRowCount; i++)
                {
                    int curIndex = i * itemColumnCount;
                    int nextIndex = (i + 1) * itemColumnCount;
                    nextIndex %= itemList.Count;

                    if (itemList[curIndex].transform.position.y - itemHalfSize > scrollYMin)
                    {
                        if (itemList[nextIndex].transform.position.y + itemHalfSize < scrollYMin)
                        {
                            UpdateItemsPos(VerticalType.Up, nextIndex);
                        }
                    }
                }
            }
        }

        lastValue = curValue;
    }

    /// <summary>
    /// 更新Item位置
    /// </summary>
    /// <param name="itemIndex"></param>
    private void UpdateItemsPos(VerticalType type, int itemIndex)
    {
        Canvas.ForceUpdateCanvases();

        if (type == VerticalType.Up)
        {
            if (content.GetChild(0).GetComponent<UIItem>().GetItemData().data == dataList[0].data) return;
            for (int i = itemColumnCount - 1; i > -1; i--)
            {
                var index = itemIndex + i;
                itemList[index].transform.SetAsFirstSibling();
            }

            UpdateItemsData(itemIndex, type);

            scroll.verticalNormalizedPosition = 0;
        }
        else if(type == VerticalType.Down)
        {
            if (UpdateItemsData(itemIndex, type) == false) return;

            for (int i = 0; i < itemColumnCount; i++)
            {
                var index = itemIndex + i;
                itemList[index].transform.SetAsLastSibling();
            }
            scroll.verticalNormalizedPosition = 1;
        }
    }

    /// <summary>
    /// 更新数据
    /// </summary>
    private bool UpdateItemsData(int itemIndex,VerticalType type)
    {
        if (type == VerticalType.Up)
        {
            var curItemData = gridLayoutGroup.transform.GetChild(5).GetComponent<UIItem>().GetItemData();
            var tempIndex = dataList.IndexOf(curItemData);

            for (int i = itemColumnCount - 1; i > -1; i--)
            {
                var index = itemIndex + i;
                tempIndex--;
                itemList[index].GetComponent<UIItem>().UpdateItemData(dataList[tempIndex]);
            }
        }
        else if (type == VerticalType.Down)
        {
            for (int i = 0; i < itemColumnCount; i++)
            {
                var index = itemIndex + i;
                if (dataIndex >= dataList.Count) return false;
                itemList[index].GetComponent<UIItem>().UpdateItemData(dataList[dataIndex]);
                dataIndex++;
            }
        }
        return true;
    }

    /// <summary>
    /// 计算有多少列
    /// </summary>
    /// <param name="width">scrollView的宽度</param>
    /// <param name="left">左边距</param>
    /// <param name="right">右边距</param>
    /// <param name="space">Item间距</param>
    /// <param name="size">item宽度</param>
    /// <returns></returns>
    private int CalculateColumnCount(float width,float left,float right,float space,float size)
    {
        int count = 0;
        var temp = width - (left + right);
        count = (int)(temp + space) / (int)(size + space);
        return count;
    }

    public void ItemBtnClicked(ItemData data)
    {
        Debug.Log("当前点击的Item的数据是:" + data.data);
    }
}

/// <summary>
/// 滑动方式
/// </summary>
public enum VerticalType
{
    Up,
    Down
}

没写注释,代码也比较简单,应该没啥问题。
下面是导出的包:
传送门

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人无两度s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值