Flutter ListView Builder实现单SwitchListTile选中限制咨询
实现同一时间仅一行Switch为选中状态的方案
核心思路
无需维护布尔值列表,改用单个变量记录当前选中的行索引,既简化状态管理,又天然保证同一时间只有一行处于选中状态。
具体修改步骤
- 替换状态变量:移除原
flags列表,新增int _selectedIndex变量,初始值设为-1(代表无任何行被选中)。 - 简化添加逻辑:添加新行时仅维护
names列表,无需再同步更新布尔值列表。 - 修复删除时的索引异常:删除行时,若被删除的是当前选中行,或删除行的索引在选中行之前,同步调整
_selectedIndex,避免索引越界。 - 更新Switch状态绑定:每个Switch的
value改为判断当前行索引是否等于_selectedIndex;点击开关时,将_selectedIndex设为当前行索引(开启时)或重置为-1(关闭时)。
修改后的完整代码
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final List<String> names = <String>[]; TextEditingController mc = TextEditingController(); // 记录当前选中的行索引,-1表示无选中 int _selectedIndex = -1; addItemToList() { setState(() { if (mc.text.isNotEmpty) { names.add(mc.text); } }); } deleteItemFromList() { setState(() { if (names.isNotEmpty) { // 处理删除后的选中索引逻辑 if (_selectedIndex == names.length - 1) { _selectedIndex = -1; } else if (_selectedIndex != -1) { _selectedIndex -= 1; } names.removeLast(); } }); } @override Widget build(BuildContext context) { Widget space = const SizedBox(height: 5); Widget myinput = TextField( controller: mc, decoration: InputDecoration(border: OutlineInputBorder(), labelText: 'Name')); Widget btnAdd = ElevatedButton(onPressed: addItemToList, child: const Text('Add')); Widget btnRemove = ElevatedButton(onPressed: deleteItemFromList, child: const Text('Remove')); Widget mylist = SizedBox( width: 800, height: 500, child: ListView.builder( shrinkWrap: true, itemCount: names.length, itemBuilder: (BuildContext context, int index) { return SwitchListTile( title: Text(names[index], style: const TextStyle(fontSize: 11)), value: index == _selectedIndex, onChanged: (bool value) { setState(() { _selectedIndex = value ? index : -1; }); }, ); }, ), ); return MaterialApp( home: Scaffold( resizeToAvoidBottomInset: false, body: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( padding: const EdgeInsets.all(5), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ space, myinput, space, btnAdd, space, btnRemove, space, mylist, space ], ), ), ], ), ), ), ); } }
额外优化说明
- 移除冗余的
SingleChildScrollView嵌套,避免多重滚动冲突 - 用
const修饰常量Widget,提升渲染性能 - 增加删除操作时的空列表判断,防止报错
内容的提问来源于stack exchange,提问作者DktPhl2018
相关产品推荐
相关产品推荐

