如何在Flutter中实现筛选容器跳转列表的设计?
Flutter 筛选+列表跳转实现方案
1. 定义核心数据模型
先搭建基础的数据结构,关联分类、专案和子专案:
// 筛选分类模型 class FilterCategory { final String id; final String name; bool isSelected; FilterCategory({required this.id, required this.name, this.isSelected = false}); } // 主专案模型 class Project { final String id; final String title; final String categoryId; // 关联筛选分类ID final List<SubProject> subProjects; // 跳转后展示的子专案列表 Project({ required this.id, required this.title, required this.categoryId, required this.subProjects, }); } // 子专案模型 class SubProject { final String id; final String name; SubProject({required this.id, required this.name}); }
2. 实现可交互筛选容器
用横向滚动的Row实现筛选标签,点击时切换选中状态并触发列表筛选:
Widget buildFilterBar(List<FilterCategory> categories, Function(FilterCategory) onTap) { return SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: categories.map((category) { return GestureDetector( onTap: () => onTap(category), child: Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: category.isSelected ? Colors.blueAccent : Colors.grey.shade200, borderRadius: BorderRadius.circular(20), ), child: Text( category.name, style: TextStyle( color: category.isSelected ? Colors.white : Colors.black87, fontWeight: category.isSelected ? FontWeight.w600 : FontWeight.normal, ), ), ), ); }).toList(), ), ); }
3. 专案列表筛选逻辑
在State类中维护选中状态和过滤后的列表,支持单选/多选筛选(示例为单选):
class _ProjectListPageState extends State<ProjectListPage> { List<FilterCategory> _categories = [ FilterCategory(id: '1', name: '分类A'), FilterCategory(id: '2', name: '分类B'), FilterCategory(id: '3', name: '分类C'), ]; List<Project> _allProjects = [ Project( id: 'p1', title: '专案1', categoryId: '1', subProjects: [SubProject(id: 'sp1', name: '子专案1-1'), SubProject(id: 'sp2', name: '子专案1-2')], ), Project( id: 'p2', title: '专案2', categoryId: '2', subProjects: [SubProject(id: 'sp3', name: '子专案2-1')], ), ]; List<Project> _filteredProjects = []; @override void initState() { super.initState(); _filteredProjects = _allProjects; // 默认显示全部专案 } void _handleCategoryTap(FilterCategory tappedCategory) { setState(() { // 单选逻辑:仅选中当前点击的分类 for (var category in _categories) { category.isSelected = category.id == tappedCategory.id; } // 根据选中分类筛选专案 _filteredProjects = _allProjects.where((project) => project.categoryId == tappedCategory.id).toList(); }); }
4. 列表项点击跳转至子专案页面
用Navigator.push传递子专案数据到新页面:
Widget buildProjectList() { return ListView.builder( itemCount: _filteredProjects.length, itemBuilder: (context, index) { final project = _filteredProjects[index]; return ListTile( title: Text(project.title), trailing: const Icon(Icons.arrow_forward_ios), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => SubProjectPage(subProjects: project.subProjects), ), ); }, ); }, ); } // 子专案页面 class SubProjectPage extends StatelessWidget { final List<SubProject> subProjects; const SubProjectPage({super.key, required this.subProjects}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('子专案列表')), body: ListView.builder( itemCount: subProjects.length, itemBuilder: (context, index) { return ListTile(title: Text(subProjects[index].name)); }, ), ); } }
5. 页面整体组装
将筛选栏和列表组合到主页面中:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('专案列表')), body: Column( children: [ buildFilterBar(_categories, _handleCategoryTap), Expanded(child: buildProjectList()), ], ), ); }
扩展说明
- 若需多选筛选,修改
_handleCategoryTap逻辑,仅切换当前分类的选中状态,筛选时匹配所有选中分类的ID - 数据量大时,可结合
FutureBuilder处理异步数据加载 - 样式可根据设计图调整,比如筛选容器的阴影、列表项的卡片布局等
内容的提问来源于stack exchange,提问作者tesseract
相关产品推荐
相关产品推荐

