Flutter中生成TextButton列表时如何正确获取点击对应索引?
我写了一段生成TableRow列表的代码,循环里给每个TextButton绑定了点击事件,想打印对应的index,但不管点哪个按钮,控制台都只输出循环最后一个index的值。
简化后的核心代码:
list.add(TextButton( onPressed: () { int temp = index; print(temp); }, child: Text(myText), ));
完整函数代码:
List<TableRow> generateTables() { List<TableRow> list = []; int index = 0; for (Map element in exerciseList) { String exName = element["name"]; Icon? icon = correspIcon(element); list.add( TableRow( children: [ TextButton( onPressed: () { int temp = index; print(temp); }, style: TextButton.styleFrom( minimumSize: Size.zero, padding: const EdgeInsets.all(4.0), tapTargetSize: MaterialTapTargetSize.shrinkWrap, alignment: Alignment.centerLeft, ), child: Text( exName, style: TextStyle( fontFamily: "ArialRounded", fontSize: 20, color: Colors.white.withAlpha(240)), ), ), icon ?? const SizedBox() ], ), ); index++; } return list; }
我希望点击第n个TextButton时,能输出对应的n-1索引,该怎么改?
解决方案
这是Dart闭包捕获变量的常见问题:所有onPressed闭包都捕获了同一个index变量的引用,而非当前循环的数值。循环结束后index已经是最后一个值,所以所有按钮点击时都会读取这个最终值。
方法1:循环内创建局部变量捕获当前index
每次循环时,把当前index赋值给局部变量,让闭包捕获这个局部变量的数值:
for (Map element in exerciseList) { String exName = element["name"]; Icon? icon = correspIcon(element); // 用局部变量保存当前循环的index值 int currentIndex = index; list.add( TableRow( children: [ TextButton( onPressed: () { print(currentIndex); }, // 原有样式、child代码保持不变 ), icon ?? const SizedBox() ], ), ); index++; }
方法2:使用asMap().forEach带索引遍历
借助列表的asMap()方法将列表转为键值对(键为索引,值为元素),再用forEach遍历,直接获取当前元素的索引:
List<TableRow> generateTables() { List<TableRow> list = []; exerciseList.asMap().forEach((index, element) { String exName = element["name"]; Icon? icon = correspIcon(element); list.add( TableRow( children: [ TextButton( onPressed: () { print(index); }, style: TextButton.styleFrom( minimumSize: Size.zero, padding: const EdgeInsets.all(4.0), tapTargetSize: MaterialTapTargetSize.shrinkWrap, alignment: Alignment.centerLeft, ), child: Text( exName, style: TextStyle( fontFamily: "ArialRounded", fontSize: 20, color: Colors.white.withAlpha(240)), ), ), icon ?? const SizedBox() ], ), ); }); return list; }
方法3:使用List.generate生成列表
如果exerciseList是固定长度的列表,直接用List.generate创建TableRow列表,可直接获取当前索引:
List<TableRow> generateTables() { return List.generate(exerciseList.length, (index) { Map element = exerciseList[index]; String exName = element["name"]; Icon? icon = correspIcon(element); return TableRow( children: [ TextButton( onPressed: () { print(index); }, style: TextButton.styleFrom( minimumSize: Size.zero, padding: const EdgeInsets.all(4.0), tapTargetSize: MaterialTapTargetSize.shrinkWrap, alignment: Alignment.centerLeft, ), child: Text( exName, style: TextStyle( fontFamily: "ArialRounded", fontSize: 20, color: Colors.white.withAlpha(240)), ), ), icon ?? const SizedBox() ], ); }); }
内容的提问来源于stack exchange,提问作者Guereak
相关产品推荐
相关产品推荐

