Flutter中Stack如何结合索引使用Positioned避免ParentData报错
开发Flutter页面时需要基于列表索引动态配置Positioned组件的位置参数,此前采用Stack -> ListView.builder -> Positioned的嵌套结构时触发应用崩溃,报错信息如下:
Incorrect use of ParentDataWidget.
The ParentDataWidget Positioned(left: 157.2) wants to apply ParentData of type StackParentData to a RenderObject, which has been set up to accept ParentData of incompatible type FlexParentData.
Usually, this means that the Positioned widget has the wrong ancestor RenderObjectWidget. Typically, Positioned widgets are placed directly inside Stack widgets. The offending Positioned is currently placed inside a Row widget.
Positioned组件的合法嵌套规则为必须直接作为Stack的直系子组件,不能嵌套在ListView、Row这类Flex布局/滚动组件下,否则会触发ParentData类型不匹配的错误。
本次使用的示例数据源如下:
final myList = [ {"data": 100.0}, {"data": 200.0}, {"data": 300.0}, {"data": 400.0}, {"data": 500.0} ];
需求为在符合组件嵌套规范的前提下,遍历列表获取索引,将Positioned的left参数绑定为列表对应项的data值。
放弃在Stack内部嵌套ListView.builder生成Positioned的思路,直接在Stack的children属性中通过列表的map方法遍历生成所有Positioned组件即可,所有生成的Positioned都会直接作为Stack的子组件,完全符合嵌套规范。
代码结构如下:
Stack( alignment: AlignmentDirectional.topStart, children: [ // 遍历列表生成所有定位组件 ...myList.asMap().entries.map((entry) { // 当前遍历项索引 final index = entry.key; // 当前遍历项数据 final item = entry.value; return Positioned( // 绑定对应项的data值作为left偏移 left: item["data"] as double, child: Directionality( textDirection: TextDirection.ltr, child: MySimpleIcons( iconName: MyIcons.bookProfile, iconColor: theme.darkGrey, iconSize: 24, ), ), ); }).toList(), // 其余Stack子组件可直接在此处追加 // another widgets ], )
- 调用列表的
asMap()方法可将列表转为「索引-内容」的键值对结构,无需依赖ListView.builder即可在遍历时拿到索引值 - 遍历生成的
Positioned组件通过展开运算符...直接插入到Stack的children数组中,中间没有嵌套滚动/Flex类组件,完全满足Positioned的父组件约束 - 如果需要针对不同索引的项配置差异化的定位参数、子组件内容,直接在map的回调逻辑中根据index分支处理即可
内容的提问来源于stack exchange,提问作者user17838882

