前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity-UGUI无限循环列表

Unity-UGUI无限循环列表

作者头像
祝你万事顺利
发布2019-07-26 14:58:41
5K0
发布2019-07-26 14:58:41
举报
文章被收录于专栏:Unity游戏开发

Unity版本:2017.4

简介: UGUI使用ScrollView、GridLayoutGroup实现无限循环列表,支持数据刷新,支持跳转,支持动态插入/删除

使用说明: 点击UI中的ID进行删除,键盘按下A添加ID。 在Inspector面板中输入MaxItemCount 列表最大数量。TargetID输入要跳转的ID,键盘按下Space跳转到要查找的ID。

代码语言:javascript
复制
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CSInfiniteScrolling : MonoBehaviour
{

    public int maxItemCount = 0;
    public int targetID = 0;

    private int rowCount = 0;
    private int columnCount = 0;
    private int curTopIndex = 0;
    private int initializedBottomIndex = 0;
    private int curBottomIndex = 0;
    private int contentCurTopPosY = 0;
    private int oneBlockHeight = 0;
    private int curIndex = 0;

    private List<int> itemIDs;

    private ScrollRect scrollRect;
    private RectTransform content;
    private GridLayoutGroup contentGridLayoutGroup;

    private void Awake()
    {
        scrollRect = GetComponent<ScrollRect>();

        content = scrollRect.content;
        contentGridLayoutGroup = content.GetComponent<GridLayoutGroup>();


        columnCount = (int)(content.rect.width - contentGridLayoutGroup.spacing.x) / (int)contentGridLayoutGroup.cellSize.x;
        if (columnCount != 0)
        {
            rowCount = (int)Mathf.Ceil(content.transform.childCount / columnCount);
            curBottomIndex = (rowCount - 1) * columnCount;
            initializedBottomIndex = curBottomIndex;
        }

        oneBlockHeight = (int)(contentGridLayoutGroup.cellSize.y + contentGridLayoutGroup.spacing.y);
        content.sizeDelta = new Vector2(content.sizeDelta.x, (int)Mathf.Ceil((float)maxItemCount / (float)columnCount) * oneBlockHeight);//向上取整

        itemIDs = new List<int>();
        for (int i = 0; i < maxItemCount; i++)
        {
            itemIDs.Add(i);
        }

    }

    // Use this for initialization
    void Start()
    {
        scrollRect = GetComponent<ScrollRect>();
        scrollRect.onValueChanged.AddListener(ListenerMethod);
        FreshBackpack();
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            JumpToTargetID(targetID);
        }
        if (Input.GetKeyDown(KeyCode.A))
        {
            AddRandomID();
            FreshBackpack();
        }
    }

    private void AddRandomID()
    {
        if (itemIDs.Count<maxItemCount)
        {
            System.Random random = new System.Random();
            itemIDs.Add(random.Next(0, 100));
        }
        else
        {
            Debug.Log("Backpack is Full!");
        }
    }

    private void InitializedChildButton(Transform transformChild,int index = -1)
    {
        if (index != -1)
        {
            Button.ButtonClickedEvent buttonClickedEvent = new Button.ButtonClickedEvent();
            buttonClickedEvent.AddListener(() => {
                itemIDs.RemoveAt(index);
                FreshBackpack();
            });
            transformChild.GetComponent<Button>().onClick = buttonClickedEvent;
        }
        else
        {
            Button.ButtonClickedEvent buttonClickedEvent = new Button.ButtonClickedEvent();
            buttonClickedEvent.AddListener(() => {
                Debug.Log("None Object");
            });
            transformChild.GetComponent<Button>().onClick = buttonClickedEvent;
        }
    }

    private void ListenerMethod(Vector2 contentPos)
    {
        if ((content.localPosition.y - contentCurTopPosY) > oneBlockHeight)
        {
            while ((content.localPosition.y - contentCurTopPosY) > oneBlockHeight)
            {
                contentCurTopPosY = contentCurTopPosY + oneBlockHeight;
                for (int i = 0; i < columnCount; i++)
                {
                    RectTransform rectTransform = content.transform.GetChild(curTopIndex + i).GetComponent<RectTransform>();
                    rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, rectTransform.anchoredPosition.y - oneBlockHeight * rowCount);
                }

                curTopIndex += columnCount;
                curBottomIndex += columnCount;
                curTopIndex = curTopIndex % content.childCount;
                curBottomIndex = curBottomIndex % content.childCount;
                curIndex += columnCount;
            }
            FreshBackpack();
        }
        else if ((content.localPosition.y - contentCurTopPosY) < -contentGridLayoutGroup.spacing.y)
        {
            while ((content.localPosition.y - contentCurTopPosY) < -contentGridLayoutGroup.spacing.y)
            {
                contentCurTopPosY = contentCurTopPosY - oneBlockHeight;
                for (int i = 0; i < columnCount; i++)
                {
                    RectTransform rectTransform = content.transform.GetChild(curBottomIndex + i).GetComponent<RectTransform>();
                    rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, rectTransform.anchoredPosition.y + oneBlockHeight * rowCount);
                }

                curTopIndex = (curTopIndex + content.childCount) - columnCount;
                curBottomIndex = (curBottomIndex + content.childCount) - columnCount;
                curTopIndex = curTopIndex % content.childCount;
                curBottomIndex = curBottomIndex % content.childCount;
                curIndex -= columnCount;
            }
            FreshBackpack();
        }
    }
    private void FreshBackpack()
    {
        int offset = 0;
        for (int i = 0; i < content.childCount; i++)
        {
            Transform textChild = content.GetChild((curTopIndex + i) % content.childCount).GetChild(0);
            if ((curIndex + offset) < itemIDs.Count)
            {
                textChild.GetComponent<Text>().text = "" + itemIDs[curIndex + offset];
                InitializedChildButton(content.GetChild((curTopIndex + i) % content.childCount), curIndex + offset);
                offset++;
            }
            else
            {
                textChild.GetComponent<Text>().text = "";
                InitializedChildButton(content.GetChild((curTopIndex + i) % content.childCount));
                offset++;
            }
        }
    }

    public void JumpToTargetID(int ID)
    {
        int index = -1;
        for (int i = 0; i < itemIDs.Count; i++)
        {
            if (ID == itemIDs[i])
            {
                index = i;
                break;
            }
        }

        if (index == -1)
            return;

        curIndex = index - (index % columnCount);
        curTopIndex = 0;
        curBottomIndex = initializedBottomIndex;
        float newContentLocalPosY = ((curIndex + 1) / columnCount) * oneBlockHeight;
        content.localPosition = new Vector2(content.localPosition.x, ((curIndex + 1) / columnCount) * oneBlockHeight);
        contentCurTopPosY = (int)content.localPosition.y;

        int curTopRowIndex = curIndex / columnCount;
        for (int i = 0; i < content.childCount; i++)
        {
            RectTransform rectTransform = content.GetChild(i).GetComponent<RectTransform>();
            int newAnchoredPosY = (curTopRowIndex * -oneBlockHeight) + (-oneBlockHeight * (i / columnCount) - (int)(0.5 * content.GetComponent<GridLayoutGroup>().cellSize.y));
            rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, newAnchoredPosY);
        }
        FreshBackpack();
    }
}

物品没有直接挂载Button,通过代码控制Button的挂载

代码语言:javascript
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PressToDelID : MonoBehaviour {
    private Button button;
    private void Awake()
    {
        button = gameObject.GetComponent<Button>();

        if (button == null)
        {
            gameObject.AddComponent<Button>();
        }
    }
}

用Lua实现

代码语言:javascript
复制
import "UnityEngine"
import "UnityEngine.UI"

local breakSocketHandle,debugXpCall = require("LuaDebugjit")("localhost",7003)
LuaTimer.Add(0,1000,function(id)
    breakSocketHandle()
end)

local scrollRect;
local content;
local contentGridLayoutGroup;
local columnCount;
local rowCount;
local initializedBottomIndex;
local oneBlockHeight;
local maxItemCount = 0;
local itemIDs = {};
local scrollRect;

local contentCurTopPosY = 0;
local curTopIndex = 0;
local curBottomIndex = 0;
local curIndex = 1;

local class = {}

function main()
    maxItemCount = 40;

    scrollRect = GameObject.Find("Canvas/Backpack"):GetComponent(UI.ScrollRect);
    
    content = scrollRect.content;
    contentGridLayoutGroup = content:GetComponent(UI.GridLayoutGroup);

    columnCount = math.floor((content.rect.width - contentGridLayoutGroup.spacing.x)/contentGridLayoutGroup.cellSize.x);
    if columnCount ~= 0 then
        rowCount = math.ceil( content.childCount/columnCount );
        curBottomIndex = (rowCount - 1)*columnCount;
        initializedBottomIndex = curBottomIndex;
    end

    oneBlockHeight = contentGridLayoutGroup.cellSize.y + contentGridLayoutGroup.spacing.y;
    local contentSizeDeltaY = math.floor( oneBlockHeight * (math.ceil(maxItemCount / columnCount))) ;
    content.sizeDelta = UnityEngine.Vector2(content.sizeDelta.x,contentSizeDeltaY);

    for i=1,maxItemCount do
        table.insert(itemIDs,i);
    end

    scrollRect.onValueChanged:AddListener(ListenerMethod);
    FreshBackpack();

    return class;
end

function class : Update()
    if UnityEngine.Input.GetKeyDown(KeyCode.Space) then
        JumpToTargetID(12);
    end
    if UnityEngine.Input.GetKeyDown(KeyCode.A) then
        if #itemIDs < maxItemCount then
            table.insert( itemIDs,math.random(0,100) );
            FreshBackpack();
        else
            print("BP Full!");
        end
    end
end

function ListenerMethod()
    if ((content.localPosition.y - contentCurTopPosY) > oneBlockHeight) then
        while ((content.localPosition.y - contentCurTopPosY) > oneBlockHeight)
            do
                contentCurTopPosY = contentCurTopPosY + oneBlockHeight;
                for i=1,columnCount do
                    local child = content.transform:GetChild(curTopIndex + i - 1);
                    local rectTransform = child:GetComponent(UnityEngine.RectTransform);
                    rectTransform.anchoredPosition = UnityEngine.Vector2(rectTransform.anchoredPosition.x, rectTransform.anchoredPosition.y - oneBlockHeight * rowCount);
                end
                curTopIndex = curTopIndex + columnCount;
                curBottomIndex =    curBottomIndex+ columnCount;
                curTopIndex = curTopIndex % content.childCount;
                curBottomIndex = curBottomIndex % content.childCount;
                curIndex =curIndex+ columnCount;
            end
            FreshBackpack();
    elseif ((content.localPosition.y - contentCurTopPosY) < -contentGridLayoutGroup.spacing.y) then
        while ((content.localPosition.y - contentCurTopPosY) < -contentGridLayoutGroup.spacing.y) do
                contentCurTopPosY = contentCurTopPosY - oneBlockHeight;
                for i=1,columnCount do
                    local rectTransform = content.transform:GetChild(curBottomIndex + i -1):GetComponent(UnityEngine.RectTransform);
                    rectTransform.anchoredPosition = UnityEngine.Vector2(rectTransform.anchoredPosition.x, rectTransform.anchoredPosition.y + oneBlockHeight * rowCount);
                end
                curTopIndex = (curTopIndex + content.childCount) - columnCount;
                curBottomIndex = (curBottomIndex + content.childCount) - columnCount;
                curTopIndex = curTopIndex % content.childCount;
                curBottomIndex = curBottomIndex % content.childCount;
                curIndex =curIndex - columnCount;
        end
            FreshBackpack();
    end
end

function FreshBackpack()
    local offset = 0;
    for i=1,content.childCount do
        local contentChild = content:GetChild((curTopIndex + i - 1) % content.childCount);
        local textChild = contentChild:GetChild(0);
        if ((curIndex + offset) <= #itemIDs) then
            textChild:GetComponent(UI.Text).text = tostring(itemIDs[curIndex + offset]) ;
            InitializedChildButton(contentChild, curIndex + offset);
        else
            textChild:GetComponent(UI.Text).text = "";
            InitializedChildButton(contentChild);
        end
        offset = offset + 1;
    end
end

function InitializedChildButton(contentChild,index)
    local buttonClickedEvent = Button:ButtonClickedEvent();
            buttonClickedEvent:AddListener(function()
                if (index ~= nil) then
                    table.remove( itemIDs,index );
                    FreshBackpack();
                else
                    print("None Object");
                end
            end);
    contentChild:GetComponent(UI.Button).onClick = buttonClickedEvent;
end

function JumpToTargetID( ID )
    local index;
    for i=1,#itemIDs do
        if ID == itemIDs[i] then
            index = i;
            break;
        end
    end
    if index == nil then
        return nil;
    end

    curIndex = index - (index - 1 ) % columnCount;
    curTopIndex = 0;
    curBottomIndex = initializedBottomIndex;
    local newContentLocalPosY = math.floor( curIndex  / columnCount ) * oneBlockHeight;
    content.localPosition = UnityEngine.Vector2(content.localPosition.x,newContentLocalPosY);
    contentCurTopPosY =content.localPosition.y;

    local curTopRowIndex = (curIndex-1) / columnCount;
    for i=1,content.childCount do
        local rectTransform = content:GetChild(i-1):GetComponent(UnityEngine.RectTransform);
        local newAnchoredPosY = (curTopRowIndex * -oneBlockHeight) + (-oneBlockHeight * math.floor((i-1) / columnCount) - math.floor(0.5 * content:GetComponent(UI.GridLayoutGroup).cellSize.y));
        rectTransform.anchoredPosition = UnityEngine.Vector2(rectTransform.anchoredPosition.x,newAnchoredPosY);
    end

    FreshBackpack();
end
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.07.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档