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

如何在Flutter Modal Bottom Sheet中添加带复选框的下拉列表?

Flutter Modal Bottom Sheet 集成带复选框的多选下拉组件

以下是在Modal Bottom Sheet中添加带复选框列表的多选下拉组件的完整实现,点击下拉区域会弹出包含复选框的选项列表,选中后会将已选内容展示在下拉框中:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Modal Bottom Sheet Demo')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => _showModalBottomSheet(context),
          child: const Text('打开底部弹窗'),
        ),
      ),
    );
  }

  void _showModalBottomSheet(BuildContext context) {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (context) => const _ModalBottomSheetContent(),
    );
  }
}

class _ModalBottomSheetContent extends StatefulWidget {
  const _ModalBottomSheetContent();

  @override
  State<_ModalBottomSheetContent> createState() => _ModalBottomSheetContentState();
}

class _ModalBottomSheetContentState extends State<_ModalBottomSheetContent> {
  // 可选选项列表
  final List<String> _options = ['选项1', '选项2', '选项3', '选项4', '选项5'];
  // 保存选中的选项
  List<String> _selectedOptions = [];
  // 下拉框显示的文本
  String _displayText = '请选择选项';

  // 弹出多选复选框列表
  void _showMultiSelectDialog() {
    showModalBottomSheet(
      context: context,
      builder: (context) => Container(
        padding: const EdgeInsets.all(16),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text(
              '选择选项',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            Expanded(
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: _options.length,
                itemBuilder: (context, index) {
                  final option = _options[index];
                  return CheckboxListTile(
                    title: Text(option),
                    value: _selectedOptions.contains(option),
                    onChanged: (value) {
                      setState(() {
                        if (value == true) {
                          _selectedOptions.add(option);
                        } else {
                          _selectedOptions.remove(option);
                        }
                      });
                    },
                  );
                },
              ),
            ),
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                TextButton(
                  onPressed: () => Navigator.pop(context),
                  child: const Text('取消'),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      // 更新显示文本
                      if (_selectedOptions.isEmpty) {
                        _displayText = '请选择选项';
                      } else {
                        _displayText = _selectedOptions.join(', ');
                      }
                    });
                    Navigator.pop(context);
                  },
                  child: const Text('确定'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(
        bottom: MediaQuery.of(context).viewInsets.bottom,
      ),
      child: Container(
        padding: const EdgeInsets.all(16),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              '底部弹窗内容',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 24),
            // 带复选框的下拉组件
            InkWell(
              onTap: _showMultiSelectDialog,
              child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(_displayText),
                    const Icon(Icons.arrow_drop_down),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),
            // 其他弹窗内容示例
            const TextField(
              decoration: InputDecoration(
                labelText: '输入框示例',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('确认'),
            ),
          ],
        ),
      ),
    );
  }
}

关键实现说明

  • 状态管理:通过_selectedOptions列表保存用户选中的选项,_displayText控制下拉框的展示文本
  • 下拉触发:用InkWell包裹容器模拟下拉按钮,点击后弹出带复选框列表的底部弹窗
  • 复选框列表:使用CheckboxListTile实现选项的多选功能,点击复选框实时更新选中状态
  • 结果回显:点击确定按钮后,将选中的选项用逗号拼接后显示在下拉框中

内容的提问来源于stack exchange,提问作者Kanwarpreet Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:37:40