Unity - UIWidgets 6. 顯示列表


為了更貼近游戲實際ui的效果和使用環境, 從而討論上一節遺留的問題, 列表顯示是必不可少的
參考
修改之前的HomeRoute,

        private Widget CreateListTest()
        {
            ListView listView = ListView.builder(
                scrollDirection: Axis.vertical,
                itemExtent: 20,
                itemCount: 100,
                itemBuilder: (context, index) =>
                {
                    return new Text(data: index.ToString());
                }
                );

            return listView;
        }

        private Widget GetWidget()
        {
            Scaffold scaffold = new Scaffold(
                appBar: new AppBar(
                    title: new Text("首頁")
                    ),
                body: CreateListTest()
                );

            return scaffold;
        }

創建了一個列表, 顯示從0到99的數字, 每個列表項高度為20(邏輯高度), 效果如下

通過UIWidgets Inspector可以看到列表項是循環回收的(即看不到的列表項不作為一個UI節點存在), 但這個節點大概已經嵌套了四五十層... 對性能不太信任

顯示背包道具

下面要做的是模擬一個顯示背包道具的操作, 一個簡單的列表顯示玩家背包中的每種道具的名字和一句說明(為簡化, 道具通通不可疊加)
即提前准備好state, 暫時沒有action

首先我准備了幾個道具

// Item.cs

using System.Collections.Generic;

namespace Data
{
    // 道具的數據類, 非常簡單
    public class Item
    {
        public int id;
        public string name;
        public string description;

        // 臨時模擬一個配置表
        public static Dictionary<int, Item> Table = new Dictionary<int, Item>()
        {
            { 1, new Item { id = 1, name = "木棍", description = "一根沒什么用的木棍" } },
            { 2, new Item { id = 2, name = "石頭", description = "一塊沒什么用的石頭" } },
            { 3, new Item { id = 3, name = "干草", description = "一把沒什么用的干草" } },
        };
    }
}

然后給主角的背包里塞了10個木棍, 10個石頭, 5個干草

// GlobalState.cs

using System.Collections.Generic;

namespace UI
{
    public class GlobalState
    {
        public List<int> Items;

        public GlobalState()
        {
            Items = new List<int>
            {
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                3, 3, 3, 3, 3,
            };
        }
    }
}

修改列表顯示

// HomeRoute.cs

        private Widget CreateListTest()
        {
            var widget = new StoreConnector<GlobalState, List<int>>(
                converter: (state) => state.Items,
                builder: (context, list, dispatcher) => ListView.builder(
                    itemExtent: 20,
                    itemCount: list.Count,
                    itemBuilder: (context2, index) =>
                    {
                        int itemId = list[index];
                        Data.Item data = Data.Item.Table[itemId];
                        return new Text(data: $"道具名稱: {data.name}, 說明: {data.description}");
                    }
                    )
                );

            return widget;
        }

這么寫從直覺上不太對, 但目前成功了

修改背包道具

參照前面的寫法給增加兩個功能: 點擊道具列表項使用\獲取一個新道具

為了更直觀刪除了大部分道具

GlobalState.cs

using System.Collections.Generic;

namespace UI
{
    public class GlobalState
    {
        public List<int> Items;

        public GlobalState()
        {
            UnityEngine.Debug.Log("創建了新的GlobalState");
            Items = new List<int>
            {
                1, 2, 3,
            };
        }

        public GlobalState(List<int> items)
        {
            UnityEngine.Debug.Log("創建了新的GlobalState, 傳遞了items");
            Items = items;
        }
    }
}
// Actions.cs

namespace UI
{
    public class UseBagItemAction
    {
        public int positionIndex;
    }

    public class GetItemAction
    {
        public int itemId;
    }
}
// HomeRoute.cs

        public static GlobalState Reducer(GlobalState state, object action)
        {
            if (action is UseBagItemAction)
            {
                int posId = ((UseBagItemAction)action).positionIndex;
                // 這里參照了Redux規范, 復制一份新的再修改, 下同
                List<int> items = new List<int>(state.Items);
                items.RemoveAt(posId);
                return new GlobalState(items);
            }

            if (action is GetItemAction)
            {
                int itemId = ((GetItemAction)action).itemId;
                List<int> items = new List<int>(state.Items);
                items.Add(itemId);
                return new GlobalState(items);
            }

            return state;
        }

        private Widget CreateListTest()
        {
            var showList = new StoreConnector<GlobalState, List<int>>(
                converter: (state) => state.Items,
                builder: (context, list, dispatcher) => ListView.builder(
                    //itemExtent: 20,
                    itemCount: list.Count,
                    itemBuilder: (context2, index) =>
                    {
                        int itemId = list[index];
                        Data.Item data = Data.Item.Table[itemId];
                        return new RaisedButton(
                            child: new Text(data: $"{index} - 道具名稱: {data.name}, 說明: {data.description}"),
                            onPressed: () =>
                            {
                                dispatcher.dispatch(new UseBagItemAction { positionIndex = index });
                            }
                            );
                    }
                    )
                );

            var btn = new StoreConnector<GlobalState, object>(
                converter: (state) => null,
                builder: (context, _, dispathcer) => new RaisedButton(
                    child: new Text("獲得一根木棍"),
                    onPressed: () =>
                    {
                        dispathcer.dispatch(new GetItemAction { itemId = 1 });
                    }
                    )
                );

            var widget = new Column(
                children: new List<Widget> {
                    // 畫面溢出時直接報錯, 限制一下高度
                    new Container(
                        child: showList,
                        height: 400
                        ),
                    btn,
                    }
                );

            return widget;
        }

使用三個道具, 獲得三個木棍, 沒什么問題

之后就需要討論ListItem更復雜化\動效\效率優化\代碼重構等等問題了, 和這次的主題沒有關系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM