You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:31:59