Flutter中如何点击TextButton后显示包含Card的ListView
问题解决说明
现有代码核心问题
- 你定义的
getCard()返回的ListView组件没有被加入到build方法的Widget渲染树中,就算触发setState也不会显示 - 仅用
buttonClicked布尔值无法区分点击的是哪个分类按钮,不能匹配对应分类的列表内容 - 根布局结构错误,没有预留列表的展示位置
解决方案
- 把状态变量从
bool buttonClicked改成存储当前选中的分类索引的int? selectedTabIndex,默认值为null代表未选中任何分类 - 调整body的根布局为
Column,先放顶部分类按钮栏,再根据selectedTabIndex的值判断是否展示对应列表 - 每个分类按钮点击时更新选中的索引值,同时新增按钮选中态样式优化体验
- 根据选中的索引加载对应分类的列表数据
修改后完整代码
class _CardScreenState extends State<CardScreen> { // 存储当前选中的分类索引,null代表未选中 int? selectedTabIndex; // 分类名称列表 List<String> tabTitles = [ "On hold", "In progress", "Needs review", "Approved", ]; // 模拟每个分类对应的列表数据,可根据实际需求替换 Map<int, List<String>> tabListData = { 0: ["待处理任务1", "待处理任务2", "待处理任务3"], 1: ["进行中任务1", "进行中任务2"], 2: ["待审核任务1", "待审核任务2", "待审核任务3", "待审核任务4"], 3: ["已通过任务1"], }; @override Widget build(BuildContext context) { return Scaffold( floatingActionButtonLocation: FloatingActionButtonLocation.endTop, floatingActionButton: FloatingActionButton( backgroundColor: Colors.tealAccent, onPressed: () { Get.back(); }, child: const Icon(Icons.arrow_back), ), body: Container( color: Colors.black, width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, alignment: Alignment.topCenter, // 改为Column布局,先放顶部按钮栏,再放列表 child: Column( children: [ // 原有的顶部分类按钮栏 SizedBox( height: 150, width: 500, child: DecoratedBox( decoration: BoxDecoration(color: Colors.grey[900]), child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: List.generate(tabTitles.length, (index) { // 批量生成分类按钮,减少重复代码 bool isSelected = selectedTabIndex == index; return Expanded( child: TextButton( onPressed: () { setState(() { // 如果点击的是已选中的按钮,可以关闭列表,也可以保留,按需调整 selectedTabIndex = isSelected ? null : index; }); }, child: Text( tabTitles[index], style: TextStyle( // 选中的按钮文字高亮 color: isSelected ? Colors.tealAccent : Colors.grey[300], ), ), ), ); }), ), ), ), // 选中分类后展示对应列表 if (selectedTabIndex != null) getCard(selectedTabIndex!) ], ), ), ); } // 根据传入的分类索引加载对应列表 Widget getCard(int tabIndex) { final list = tabListData[tabIndex] ?? []; return Expanded( child: ListView.builder( padding: const EdgeInsets.all(16), itemCount: list.length, itemBuilder: (_, index) => Card( color: Colors.grey, margin: const EdgeInsets.only(bottom: 12), child: Padding( padding: const EdgeInsets.all(16), child: Text(list[index]), ), ), ), ); } }
内容的提问来源于stack exchange,提问作者Mc Ride
相关产品推荐
相关产品推荐

