Flutter:使用复选框进行下拉多选
本文向您展示了在 Flutter 中使用复选框实现下拉多选的两种不同方法。在第一种方法中,我们将从头开始构建多选。在第二种方法中,我们将使用第三方包快速完成工作。
从头开始使用复选框创建多选
应用预览
我们将要构建的应用程序有一个专业的、功能齐全的多选小部件,可显示选项列表。可以通过选中/取消选中与其关联的复选框来选择或取消选择一个选项。
当按下升高的按钮时,将显示多选对话框。它让用户在编程中选择他们最喜欢的主题。所选主题将作为筹码显示在屏幕上。
以下是我们的应用程序的运行方式:
构建自定义多选小部件
创建一个名为MultiSelect的可重用小部件,它可以获取选项列表(您可以对这些项目进行硬编码或从数据库/API 中获取它们):
// Multi Select widget // This widget is reusable class MultiSelect extends StatefulWidget { final List<String> items; const MultiSelect({Key? key, required this.items}) : super(key: key); @override State<StatefulWidget> createState() => _MultiSelectState(); } class _MultiSelectState extends State<MultiSelect> { // this variable holds the selected items final List<String> _selectedItems = []; // This function is triggered when a checkbox is checked or unchecked void _itemChange(String itemValue, bool isSelected) { setState(() { if (isSelected) { _selectedItems.add(itemValue); } else { _selectedItems.remove(itemValue); } }); } // this function is called when the Cancel button is pressed void _cancel() { Navigator.pop(context); } // this function is called when the Submit button is tapped void _submit() { Navigator.pop(context, _selectedItems); } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Select Topics'), content: SingleChildScrollView( child: ListBody( children: widget.items .map((item) => CheckboxListTile( value: _selectedItems.contains(item), title: Text(item), controlAffinity: ListTileControlAffinity.leading, onChanged: (isChecked) => _itemChange(item, isChecked!), )) .toList(), ), ), actions: [ TextButton( child: const Text('Cancel'), onPressed: _cancel, ), ElevatedButton( child: const Text('Submit'), onPressed: _submit, ), ], ); } }
完整的代码
这是您在上面的演示中看到的应用程序的代码:
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { const String title = "坚果"; return MaterialApp( debugShowCheckedModeBanner: false, title: title, theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomePage(), ); } } // Multi Select widget // This widget is reusable class MultiSelect extends StatefulWidget { final List<String> items; const MultiSelect({Key? key, required this.items}) : super(key: key); @override State<StatefulWidget> createState() => _MultiSelectState(); } class _MultiSelectState extends State<MultiSelect> { // this variable holds the selected items final List<String> _selectedItems = []; // This function is triggered when a checkbox is checked or unchecked void _itemChange(String itemValue, bool isSelected) { setState(() { if (isSelected) { _selectedItems.add(itemValue); } else { _selectedItems.remove(itemValue); } }); } // this function is called when the Cancel button is pressed void _cancel() { Navigator.pop(context); } // this function is called when the Submit button is tapped void _submit() { Navigator.pop(context, _selectedItems); } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Select Topics'), content: SingleChildScrollView( child: ListBody( children: widget.items .map((item) => CheckboxListTile( value: _selectedItems.contains(item), title: Text(item), controlAffinity: ListTileControlAffinity.leading, onChanged: (isChecked) => _itemChange(item, isChecked!), )) .toList(), ), ), actions: [ TextButton( child: const Text('取消'), onPressed: _cancel, ), ElevatedButton( child: const Text('确定'), onPressed: _submit, ), ], ); } } // Implement a multi select on the Home screen class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { List<String> _selectedItems = []; String _title = "坚果"; void _showMultiSelect() async { // a list of selectable items // these items can be hard-coded or dynamically fetched from a database/API final List<String> _items = [ 'Flutter', 'Node.js', 'React Native', 'Java', 'Docker', 'MySQL' ]; final List<String>? results = await showDialog( context: context, builder: (BuildContext context) { return MultiSelect(items: _items); }, ); // Update UI if (results != null) { setState(() { _selectedItems = results; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_title), ), body: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // use this button to open the multi-select dialog ElevatedButton( child: const Text('选出你最喜欢的技术'), onPressed: _showMultiSelect, ), const Divider( height: 30, ), // display selected items Wrap( children: _selectedItems .map((e) => Chip( label: Text(e), )) .toList(), ) ], ), ), ); } }
使用第三方插件
进行自定义多选既不复杂也不复杂。但是,如果您有紧急任务并且只想尽快进行多选,那么使用第三方插件是一个不错的选择。有几个不错的开源包供您使用:
flutter_multi_select
multiselect_formfield
flutter_multiselect
多选
结论
您已经学习了不止一种向应用程序添加多选的技术。如果你想探索更多关于现代 Flutter 开发的新鲜有趣的东西,