Flutter中如何为API数据源的ExpansionTile添加多个ListTile?
解决方案
要实现每个ExpansionTile展示多个ListTile,核心是让每个父项(MonthModel)对应一个子项列表,再通过遍历该列表生成多个ListTile,具体步骤如下:
1. 调整数据模型
先修改MonthModel,把原来单个的description字段改成子项列表,适配API返回的多子项结构:
// 修改后的MonthModel示例 class MonthModel { String playerName; // 用List<String>存储多个子项内容,也可根据API结构定义更复杂的子模型 List<String> descriptions; MonthModel({required this.playerName, required this.descriptions}); }
同时更新Constants.getMonthModel(),让它返回包含多子项的MonthModel列表,模拟API返回数据:
// 示例:修改Constants中的数据生成逻辑 class Constants { static List<MonthModel> getMonthModel() { return [ MonthModel( playerName: "一月", descriptions: ["赛事1", "赛事2", "赛事3"], ), MonthModel( playerName: "二月", descriptions: ["训练1", "训练2"], ), // 其他月份数据... ]; } }
2. 修改ExpansionTile的子项生成逻辑
在_buildPlayerModelList方法中,把原来单个的ListTile替换为遍历子项列表生成的多个ListTile,分两种场景实现:
方式一:直接生成ListTile(子项数量少)
适合子项不多的场景,直接通过map遍历生成:
Widget _buildPlayerModelList(MonthModel items) { return Card( child: ExpansionTile( title: Text( items.playerName, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500), ), // 遍历descriptions列表生成多个ListTile children: items.descriptions.map((desc) { return ListTile( title: Text( desc, style: TextStyle(fontWeight: FontWeight.w700), ), ); }).toList(), ), ); }
方式二:用ListView.builder(子项数量多)
如果子项数量较多,用ListView.builder可以避免一次性创建所有Widget,提升性能,同时要设置参数避免嵌套滚动冲突:
Widget _buildPlayerModelList(MonthModel items) { return Card( child: ExpansionTile( title: Text( items.playerName, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500), ), children: [ ListView.builder( // 让ListView自适应高度 shrinkWrap: true, // 禁用内部滚动,避免和外部ListView滚动冲突 physics: NeverScrollableScrollPhysics(), itemCount: items.descriptions.length, itemBuilder: (context, idx) { return ListTile( title: Text( items.descriptions[idx], style: TextStyle(fontWeight: FontWeight.w700), ), ); }, ) ], ), ); }
完整修改后的代码
import 'package:flutter/material.dart'; import 'package:flutter_expansion_tile_demo/Constants/Constants.dart'; import 'package:flutter_expansion_tile_demo/model/month_model.dart'; class ExpansionTileDemo extends StatefulWidget { @override _ExpansionTileDemoState createState() => _ExpansionTileDemoState(); } class _ExpansionTileDemoState extends State<ExpansionTileDemo> { List<MonthModel> monthModel; @override void initState() { monthModel = Constants.getMonthModel(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text('Expansion Tile Demo'), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 0.0), child: ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, physics: BouncingScrollPhysics(), itemCount: monthModel.length, itemBuilder: (BuildContext context, int index) { return _buildPlayerModelList(monthModel[index]); }, ), ), ); } Widget _buildPlayerModelList(MonthModel items) { return Card( child: ExpansionTile( title: Text( items.playerName, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500), ), // 这里用方式一的实现,可替换为方式二 children: items.descriptions.map((desc) { return ListTile( title: Text( desc, style: TextStyle(fontWeight: FontWeight.w700), ), ); }).toList(), ), ); } }
内容的提问来源于stack exchange,提问作者Iman Yarahmadi
相关产品推荐
相关产品推荐

