Flutter多选字段插件multiselect_field的使用
Flutter多选字段插件multiselect_field的使用
MultiSelectField 插件介绍
MultiSelectField
是一个为Flutter应用程序定制实现的多选字段。这个库提供了灵活且高度可配置的解决方案,适用于需要本地多选、实时文本过滤和更高级功能的项目。
特性
- 灵活性:完全控制小部件的设计和行为,允许根据项目需求进行精确定制。
- 本地多选:无需额外包或复杂修改即可实现多选功能。
- 高级功能:包括实时文本过滤和以芯片形式显示选定项,增强用户体验。
- 维护和进化:作为自定义实现,它允许随着项目需求的变化轻松适应和发展。
- 独立性:避免第三方依赖,提高项目稳定性和长期控制。
库信息
可以在 pub.dev 查看此库。
安装
在 pubspec.yaml
文件中添加依赖:
dependencies:
multiselect_field: ^1.6.6
然后,使用以下命令安装依赖:
flutter pub get
或者直接添加:
flutter pub add multiselect_field
使用方法
基础示例
下面是一个简单的例子,展示了如何创建一个多选字段并处理选择事件:
import 'package:flutter/material.dart';
import 'package:multiselect_field/multiselect_field.dart';
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiSelectField<Car>(
data: () => [
Choice<Car>('Ferrari'),
Choice<Car>('2', '488 GTB', metadata: Car(103, 27500, 2015)),
Choice<Car>('3', '458 Italia', metadata: Car(99, 22000, 2009)),
Choice<Car>('4', 'Portofino', metadata: Car(105, 31000, 2017)),
Choice<Car>('5', 'California T', metadata: Car(102, 25000, 2016)),
Choice<Car>('6', 'F8 Tributo', metadata: Car(104, 30000, 2019)),
],
onSelect: (selectedItems) {
// 处理选中的项目
print(selectedItems.map((item) => item.value).toList());
},
useTextFilter: true, // 启用实时文本过滤
);
}
}
属性说明
- data: 返回
Choice<T>
元素列表的函数。 - onSelect: 当项目被选中时调用的回调函数。
- title: 可选标题,取决于选择是否为空。
- footer: 可选底部组件。
- singleSelectWidget: 显示单个选中项目的可选组件。
- multiSelectWidget: 显示多个选中项目的可选组件。
- defaultData: 默认选中项目的可选列表。
- singleSelection: 是否仅允许单选,默认为
false
。 - useTextFilter: 是否启用实时文本过滤。
- decoration: 自定义装饰样式。
- padding: 内边距设置。
- textStyleSingleSelection: 单选文本样式。
高级示例
这是一个更复杂的例子,展示了更多特性的使用:
MultiSelectField<String>(
data: () => [
Choice(key: 'apple', value: 'Apple'),
Choice(key: 'banana', value: 'Banana'),
Choice(key: 'orange', value: 'Orange'),
],
defaultData: [Choice(key: 'banana', value: 'Banana')],
onSelect: (selectedItems, isFromDefaultData) {
// 更新选择状态
},
title: (isEmpty) => Text(isEmpty ? 'Select a fruit' : 'Selected fruits'),
singleSelection: false,
useTextFilter: true,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(5),
),
padding: EdgeInsets.all(10),
multiSelectWidget: (item) => Chip(
label: Text(item.value),
onDeleted: () {
// 移除选中项目
},
),
);
示例应用
这里提供了一个完整的示例应用代码,展示了如何结合各种特性来构建一个多选字段界面:
import 'package:flutter/material.dart';
import 'package:multiselect_field/core/multi_select.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Multiselect field',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const MyHomePage(title: 'multiselect_field library'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Car? currentCar;
bool _singleSelection = false;
bool _useTextForFiltering = false;
bool _useFooter = false;
bool _useTitle = false;
bool _customMultiselectWidget = false;
bool _customSingleSelectWidget = false;
bool _useGroupingList = false;
bool _defaultData = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: Text(
widget.title,
style: const TextStyle(color: Colors.white),
),
),
backgroundColor: Theme.of(context).colorScheme.onPrimary,
body: Padding(
padding: const EdgeInsets.all(10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Wrap(
direction: Axis.horizontal,
spacing: 3,
children: [
Chip(
label: const Text('Use grouping on List'),
deleteIcon: _useGroupingList
? const Icon(Icons.check_box)
: const Icon(Icons.check_box_outline_blank),
onDeleted: () {
setState(() {
_useGroupingList = !_useGroupingList;
});
},
),
// ...其他Chip控件...
],
),
const SizedBox(
height: 20,
),
MultiSelectField<Car>(
title: _useTitle
? (val) => const Text(
'Optional Title Widget',
)
: null,
defaultData: _defaultData ? [choices.first] : [],
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(12)),
footer:
_useFooter ? const Text('Optional Footer Widget') : null,
data: () => _useGroupingList
? choices
: choices
.where((e) => e.key != null && e.key!.isNotEmpty)
.toList(),
onSelect: (element, isFromDefault) {
setState(() {
currentCar =
element.isNotEmpty ? element.first.metadata : null;
});
},
singleSelection: _singleSelection,
useTextFilter: _useTextForFiltering,
multiSelectWidget: _customMultiselectWidget
? (choice) {
return OutlinedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(choice.value),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Price: ${choice.metadata?.price}"),
Text("Year: ${choice.metadata?.year}"),
Text("sold: ${choice.metadata?.totalSold}"),
],
),
actions: [
OutlinedButton(
onPressed: () => Navigator.pop(context),
child: const Text('Ok'),
)
],
);
},
);
},
child: Text(choice.value));
}
: null,
singleSelectWidget: _customSingleSelectWidget
? (choice) {
return Chip(
avatar: Text("${choice.metadata?.totalSold}"),
label: Text(choice.value),
);
}
: null,
),
if (currentCar != null)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 20,
),
const Text("First car"),
Text("Price: ${currentCar!.price}"),
Text("Year: ${currentCar!.year}"),
Text("sold: ${currentCar!.totalSold}"),
],
),
const SizedBox(
height: 20,
),
Text(
"Additional properties",
style: Theme.of(context).textTheme.titleLarge,
),
ListTile(
title: Text(
"textStyleSingleSelection",
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: const Text(
"Help to create your own style for single selection using the standard widget. For more flexibility, use singleSelectWidget(Choice){}."),
),
ListTile(
title: Text(
"padding",
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: const Text("Apply padding to the entire widget."),
)
],
),
),
),
);
}
}
List<Choice<Car>> choices = [
Choice('', 'Ferrari'),
Choice('2', '488 GTB', metadata: Car(103, 27500, 2015)),
Choice('3', '458 Italia', metadata: Car(99, 22000, 2009)),
Choice('4', 'Portofino', metadata: Car(105, 31000, 2017)),
Choice('5', 'California T', metadata: Car(102, 25000, 2016)),
Choice('6', 'F8 Tributo', metadata: Car(104, 30000, 2019)),
// ...更多选项...
];
class Car {
final num totalSold;
final num price;
final int year;
Car(this.totalSold, this.price, this.year);
}
通过以上内容,您可以了解 multiselect_field
插件的基本使用方法及其提供的强大功能。希望这些信息能帮助您更好地集成和利用这个插件!
更多关于Flutter多选字段插件multiselect_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter多选字段插件multiselect_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用multiselect_field
插件的示例代码。这个插件允许你在应用中实现多选字段的功能。
首先,确保你已经在pubspec.yaml
文件中添加了multiselect_field
依赖:
dependencies:
flutter:
sdk: flutter
multiselect_field: ^^最新版本号(请替换为实际最新版本号)
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中,你可以这样使用multiselect_field
:
import 'package:flutter/material.dart';
import 'package:multiselect_field/multiselect_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter MultiSelect Field Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> _selectedOptions = [];
final List<String> _options = [
'Option 1',
'Option 2',
'Option 3',
'Option 4',
'Option 5',
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('MultiSelect Field Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Selected Options:',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 10),
Wrap(
children: List.generate(
_selectedOptions.length,
(index) => Chip(
label: Text(_selectedOptions[index]),
backgroundColor: Colors.blue.shade100,
deleteIconColor: Colors.grey,
onDeleted: () {
setState(() {
_selectedOptions.removeAt(index);
});
},
),
),
),
SizedBox(height: 20),
MultiSelectField(
title: 'Select Options',
initialValue: _selectedOptions,
options: _options,
onChanged: (newValue) {
setState(() {
_selectedOptions = newValue;
});
},
),
],
),
),
);
}
}
代码解释
- 依赖导入:确保导入了
multiselect_field
包。 - 数据准备:在
_MyHomePageState
类中,我们准备了两个列表:_selectedOptions
用于存储用户选择的项目,_options
包含所有可供选择的选项。 - UI布局:
- 使用
Column
布局来组织内容。 - 使用
Text
和Wrap
小部件来显示已选择的选项。Wrap
小部件允许选项在水平空间不足时换行显示。 - 使用
Chip
小部件来显示每个已选择的选项,并提供删除按钮。 - 使用
MultiSelectField
小部件来显示多选字段。title
参数用于设置字段标题,initialValue
参数用于设置初始值,options
参数包含所有选项,onChanged
回调函数在用户选择更改时被调用。
- 使用
这个示例展示了如何在Flutter应用中使用multiselect_field
插件来实现多选字段功能,并动态更新已选择的选项。