如何在Flutter中用ListView.builder构建iOS风格列表
问题分析
你当前代码的核心问题是给每个列表项都单独套了一个CupertinoFormSection,导致每个选项都有独立的表单边框,和期望的「整个选项列表在一个统一表单容器内」的样式不符。另外代码里还存在setState包裹异步操作、使用Material图标而非Cupertino原生图标等细节问题。
修正后的代码
body: Padding( padding: const EdgeInsets.all(8.0), child: CupertinoFormSection( // 整个选项列表统一包裹在一个CupertinoFormSection内 children: List.generate(entries.length, (i) { return GestureDetector( onTap: () async { // 先同步更新选中状态,再执行异步语言切换 setState(() { index = i; }); if (i == 0) { await context.setLocale(const Locale('en', 'US')); } else if (i == 1) { await context.setLocale(const Locale('fr', 'FR')); } else { await context.setLocale(const Locale('it', 'IT')); } }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(entries[i]), // 仅选中项显示Cupertino风格勾选图标 if (index == i) const Icon(CupertinoIcons.check_mark, color: CupertinoColors.activeBlue), ], ), ), ); }), ), )
关键修改点
- 调整层级:将
CupertinoFormSection作为外层容器,所有列表项作为它的children,实现统一的表单边框。 - 移除重复容器:删掉每个列表项独立的
CupertinoFormSection,解决重复边框问题。 - 修复状态更新:把异步语言切换移出
setState回调(setState仅负责同步更新UI状态),避免状态异常。 - 贴合iOS风格:替换Material图标为Cupertino原生图标
CupertinoIcons.check_mark。 - 优化占位逻辑:用条件判断替代
Icon(null),消除不必要的占位空间。
懒加载适配(列表项数量大时)
如果选项数量较多需要懒加载,可使用SliverCupertinoFormSection配合CustomScrollView实现:
body: CustomScrollView( slivers: [ SliverPadding( padding: const EdgeInsets.all(8.0), sliver: SliverCupertinoFormSection( header: const Text('语言选择'), // 可添加表单标题 children: List.generate(entries.length, (i) { return GestureDetector( onTap: () async { setState(() { index = i; }); if (i == 0) { await context.setLocale(const Locale('en', 'US')); } else if (i == 1) { await context.setLocale(const Locale('fr', 'FR')); } else { await context.setLocale(const Locale('it', 'IT')); } }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(entries[i]), if (index == i) const Icon(CupertinoIcons.check_mark, color: CupertinoColors.activeBlue), ], ), ), ); }), ), ), ], )
内容的提问来源于stack exchange,提问作者Giovanni
相关产品推荐
相关产品推荐

