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

如何在Flutter中实现可搜索、支持多选并存储选中项的ListView

Flutter可搜索ListView多选功能实现方案

实现思路

你需要在现有代码基础上做3处核心改动即可满足需求:

  • 新增状态变量存储选中的科目列表
  • 为列表条目增加选中状态交互、点击多选逻辑
  • 新增选中条目展示区域,支持直接取消选中

完整修改后代码

import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

// 你原有代码中已定义的科目列表,这里做示例,可根据实际情况调整
const List<String> subjectList = [
  '语文', '数学', '英语', '物理', '化学', '生物', '政治', '历史', '地理'
];

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  TextEditingController _textEditingController = TextEditingController();
  var showError = false;
  List<String> subjectListOnSearch = [];
  // 新增:存储选中的科目列表
  List<String> selectedSubjects = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Select Subject'),
        // 新增:右上角展示选中数量,点击可做提交等后续操作
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 16),
            child: Center(child: Text('已选: ${selectedSubjects.length}')),
          )
        ],
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(45),
          child: Container(
            margin: const EdgeInsets.only(left: 10, right: 10, bottom: 7),
            child: TextField(
              onChanged: (value) {
                setState(() {
                  subjectListOnSearch = subjectList
                      .where((element) => element
                      .toLowerCase()
                      .contains(value.toLowerCase()))
                      .toList();
                  showError = value.trim().isNotEmpty;
                });
              },
              controller: _textEditingController,
              decoration: InputDecoration(
                suffixIcon: Visibility(
                  visible: showError,
                  child: IconButton(
                      icon: const Icon(Icons.close, color: Colors.blue),
                      onPressed: () {
                        subjectListOnSearch.clear();
                        _textEditingController.clear();
                        setState(() {
                          showError = false;
                        });
                      }),
                ),
                hintText: 'Search Subject',
                prefixIcon: const Icon(Icons.search),
                border: InputBorder.none,
                errorBorder: InputBorder.none,
                focusedBorder: InputBorder.none,
              ),
            ),
          ),
        ),
      ),
      // 改为Column布局,顶部放选中项展示区,下方放列表
      body: Column(
        children: [
          // 新增:选中条目展示区
          if(selectedSubjects.isNotEmpty)
            Padding(
              padding: const EdgeInsets.all(10),
              child: Wrap(
                spacing: 8,
                runSpacing: 6,
                children: selectedSubjects.map((subject) {
                  return Chip(
                    label: Text(subject),
                    deleteIcon: const Icon(Icons.close, size: 16),
                    onDeleted: () {
                      setState(() {
                        selectedSubjects.remove(subject);
                      });
                    },
                  );
                }).toList(),
              ),
            ),
          // 原有列表逻辑
          Expanded(
            child: _textEditingController.text.isNotEmpty &&
                subjectListOnSearch.isEmpty
                ? const Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(
                    Icons.search_off,
                    color: Colors.red,
                    size: 100,
                  ),
                  Text('No Results Found'),
                ],
              ),
            )
                : ListView.builder(
                itemCount:
                _textEditingController.text.isNotEmpty
                    ? subjectListOnSearch.length
                    : subjectList.length,
                itemBuilder: (BuildContext context, index) {
                  final currentSubject = _textEditingController.text.isNotEmpty
                      ? subjectListOnSearch[index]
                      : subjectList[index];
                  final isSelected = selectedSubjects.contains(currentSubject);
                  return Padding(
                    padding: const EdgeInsets.only(left: 15, top: 15),
                    // 新增:ListTile增加选中状态、点击事件、选中标识
                    child: ListTile(
                      selected: isSelected,
                      selectedTileColor: Colors.blueAccent.withOpacity(0.1),
                      onTap: () {
                        setState(() {
                          if(isSelected){
                            selectedSubjects.remove(currentSubject);
                          }else{
                            selectedSubjects.add(currentSubject);
                          }
                        });
                      },
                      leading: CircleAvatar(
                        radius: 25,
                        backgroundColor: Colors.blueAccent,
                        child: Icon(MdiIcons.bookOpenPageVariant),
                      ),
                      title: Text(currentSubject),
                      trailing: isSelected
                          ? const Icon(Icons.check_circle, color: Colors.green)
                          : null,
                    ),
                  );
                }),
          ),
        ],
      ),
    );
  }
}

功能说明

  • 多选交互:点击列表条目即可切换选中状态,选中的条目会高亮底色、右侧显示勾选标识
  • 选中存储:所有选中的科目自动存入selectedSubjects列表,可直接读取该列表做后续提交等操作
  • 选中展示:页面顶部会用标签形式展示所有选中的科目,点击标签右侧的删除按钮可直接取消选中,AppBar右上角实时显示已选数量

内容的提问来源于stack exchange,提问作者Kashif Hafeez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:54:02