为了更贴近游戏实际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更复杂化\动效\效率优化\代码重构等等问题了, 和这次的主题没有关系
来源:https://www.cnblogs.com/lunoctis/p/12240455.html