您当前的位置: 首页 >  unity

Peter_Gao_

暂无认证

  • 5浏览

    0关注

    617博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

UnityUI列表的多种实现方案

Peter_Gao_ 发布时间:2021-11-25 11:33:23 ,浏览量:5

简易版

private void SetItemList(List items)
{
    foreach(var item in items)
    {    
        var cell = Instantiate(ResourcesLoader.Load("UI/prefab/UIEquip")) as GameObject;
        cell.transform.SetParent(this.itemsBg.transform);
        UIEquip script = cell.GetComponent();
        script.InitSetCell();
    }
}
优化版--协程异步加载

当列表数量多卡顿时

StartCoroutine(SetItemList(items)); //协程

private IEnumerator SetItemList(List items)
{
    foreach(var item in items)
    {    
        var cell = Instantiate(ResourcesLoader.Load("UI/prefab/UIEquip")) as GameObject;
        cell.transform.SetParent(this.itemsBg.transform);
        UIEquip script = cell.GetComponent();
        script.InitSetCell();
        
        yield return null; //每执行一次循环就先返回主流程,隔一帧再执行下一次循环
    }
}

当然,如果主流程多次调用了这个协程,会因为列表项添加到父节点时机问题导致列表项重复加载,则需要把yield reture 放到for循环外面

StartCoroutine(SetItemList(items)); //协程

private IEnumerator SetItemList(List items)
{
    yield return null; //执行到这里时先返回主流程,下一帧再回来执行循环
    ClearLayouGroup(); //先清空父节点,再循环添加列表项,防重复添加
    foreach(var item in items)
    {    
        var cell = Instantiate(ResourcesLoader.Load("UI/prefab/UIItem")) as GameObject;
        cell.transform.SetParent(this.itemsParent.transform);
        UIEquip script = cell.GetComponent();
        script.InitSetCell(); //初始化设置每个列表项实例的业务逻辑内容
    }
}

private void ClearLayouGroup() //清空列表项父节点下的所有实例
{
     var exNodeCloneList = layoutGroup.GetComponentsInChildren();
     if (exNodeCloneList == null || exNodeCloneList.Length==0)
     {
         return;
     }
        
     foreach (var node in exNodeCloneList)
     {
         Destroy(node.gameObject);
     }
}

优化版--渲染与数据分离

数据变动事件驱动渲染刷新

当列表项非常多导致卡顿,而协程也难以满足复杂业务需求时,可以考虑通过MVC分离数据和渲染的变动;

Model

public class ItemCell : object
{
	public GameObject item; //单个列表项
	public int _index; //列表项索引
}

组件:



public class ScrollRectList : MonoBehaviour/*, IDragHandler*/
{

private List hideItems = new List();
Action hideitemobject;
Action updateItem;

// 滚动列表初始化
public void Init(int DataCount)
{
        this.DestroyAllItems();

        this._content.anchoredPosition = Vector2.zero;
        this._index = -1;
        this._itemList = new List();
        this.DataCount = DataCount;

        this.OnValueChange(Vector2.zero);
        if (this.initafter != null)
        {
            this.initafter();
        }
}

public void OnValueChange(Vector2 pos)
{
        pos = isMirror? new Vector2(pos.x, pos.y*-1): pos ;
        if (this._itemList == null)
        {
            return;
        }

        int index = this.GetPosIndex();
        if (this._index != index && index > -1)
        {
            this._index = index;

            //计算不显示对象
            for (int i = 0; i < this._itemList.Count; i++)
            {
                ItemCell item = this._itemList[i];
                int itemIndex = this.getItemIndex(item);
                if (itemIndex < index * this.maxPerLine || (itemIndex >= (index + this.viewCount) * this.maxPerLine))
                {
                    this.hideItems.Add(item);
                    if (this.hideitemobject != null)
                    {
                        this.hideitemobject(item);
                    }
                }
            }

            foreach (ItemCell o in this.hideItems)
            {
                this._itemList.Remove(o);
            }

            //计算显示对象
            for (int i = this._index * this.maxPerLine; i < (this._index + this.viewCount) * this.maxPerLine; i++)
            {
                if (i < 0)
                {
                    continue;
                }
                if (i > this._dataCount - 1)
                {
                    continue;
                }
                if (this._itemList.Find(delegate (ItemCell item) { return getItemIndex(item) == i; }) == null)
                {
                    if (this.hideItems.Count > 0)
                    {
                        ItemCell o = this.hideItems[0];
                        o.item.transform.gameObject.SetActive(true);
                        this.hideItems.Remove(o);
                        this._itemList.Add(o);
                        this.updateItem(o, i);
                        this.setItemIndex(o, i);
                    }
                    else
                    {
                        this.CreateItem(i);
                    }
                }
            }

            if (this.hideItems.Count > 0)
            {
                for (int i = 0; i < this.hideItems.Count; i++)
                {
                    ItemCell item_ = this.hideItems[i];
                    item_.item.transform.gameObject.SetActive(false);
                }
            }
        }
        else
        {
            //_content.position = Vector3.zero;
        }
}


private void CreateItem(int index)
{
        GameObject o = this.createitemobject();
        if (o != null && this._content != null)
        {
            o.transform.SetParent(this._content.transform);
            o.GetComponent().pivot = isMirror?new Vector2(0f, 0f):new Vector2(0f, 1f);
            o.GetComponent().sizeDelta = new Vector2(this.cellWidth, this.cellHeight);
            o.transform.localScale = (isMirror? new Vector3(this.scale.x, this.scale.y*-1, this.scale.z): this.scale);
            ItemCell itemcell = new ItemCell();
            itemcell._index = index;
            itemcell.item = o;
            this.setItemIndex(itemcell, index);
            this.updateItem(itemcell, index);
            this._itemList.Add(itemcell);
        }
}


}

调用:

public class UIHeroPackage : Monobehavier
{

        GameObject sniperCell = null; 
        this.Grid.createitemobject = delegate ()
        {
            GameObject cell = UICommon.Instance.LoadUIItems();
            sniperCell = cell;
            return cell;
        };

        this.Grid.deleteitemobject = delegate (ItemCell cell)
        {
            UICommon.Instance.DeleteUIItems(cell.item);
        };
        

        this.Grid.updateItem = delegate (ItemCell cell, int index)
        {
            cell.item.SetActive(true);
            index *= 2;
            int tid = this.HeroDict[this.currentPage][index];
            UpdateUIItems();
            
        if (isInit)
        {
            this.Grid.Init((this.ItemsDict[this.currentPage].Count + 1) / 2);
        }
}

另外参考:

基于Unity UGUI实现的RecycleList循环列表UI容器 - HelloGalaxy - 博客园

基于Unity UGUI实现的RecycleList循环列表UI容器_weixin_30326741的博客-CSDN博客

关注
打赏
1662374065
查看更多评论
立即登录/注册

微信扫码登录

0.0472s