Flutter选择字段插件select_field的使用
Flutter选择字段插件select_field的使用
select_field
是一个简单、易用且高度可定制的输入字段插件,用于创建可选择选项的下拉列表。本文将详细介绍 select_field
插件的关键特性、限制以及如何使用它。
关键特性
使用 SelectField()
和 MultiSelectField()
,你可以:
- 完全自定义输入字段和下拉菜单以满足你的需求。
- 在下拉菜单中实现自定义小部件。
- 完全控制下拉菜单的行为。
- 轻松搜索可用选项以加快选择速度。
限制
- 不支持下拉菜单的自定义动画。
- 如果你提供自己的菜单控制器或文本控制器,则需要自己管理它们的行为。
- 提供搜索选项时,每个菜单选项的高度是固定的。
示例
单选选择字段
以下是一个简单的单选选择字段示例:
const fruitOptions = <String>[
'Apple',
'Banana',
'Strawberry',
'Cherry',
'Orange',
'Raspberry',
];
class StyledSelectField extends StatelessWidget {
const StyledSelectField({super.key});
@override
Widget build(BuildContext context) {
final options = fruitOptions
.map((fruit) => Option(label: fruit, value: fruit))
.toList();
return SelectField<String>(
options: options,
initialOption: Option<String>(
label: fruitOptions[0],
value: fruitOptions[0],
),
menuPosition: MenuPosition.below,
onTextChanged: (value) => debugPrint(value),
onOptionSelected: (option) => debugPrint(option.toString()),
inputStyle: const TextStyle(),
menuDecoration: MenuDecoration(
margin: const EdgeInsets.only(top: 8),
height: 365,
alignment: MenuAlignment.center,
backgroundDecoration: BoxDecoration(
color: Colors.green[100],
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
offset: const Offset(1, 1),
color: Colors.brown[300]!,
blurRadius: 3,
),
],
),
animationDuration: const Duration(milliseconds: 400),
buttonStyle: TextButton.styleFrom(
fixedSize: const Size(double.infinity, 60),
backgroundColor: Colors.green[100],
alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(16),
shape: const RoundedRectangleBorder(),
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.green,
),
),
separatorBuilder: (context, index) => Container(
height: 1,
width: double.infinity,
color: Colors.green,
),
),
);
}
}
自定义下拉菜单项
你还可以通过 optionBuilder
函数在下拉菜单中添加自定义小部件:
SelectField<String>(
options: options,
optionBuilder: (context, option, isSelected, onOptionSelected) {
return GestureDetector(
// 如果需要菜单的默认行为(展开或折叠),则必须调用此函数
onTap: () => onOptionSelected(option),
child: isSelected
? Container(
height: 60,
color: Colors.deepOrange.withOpacity(0.2),
child: Center(
child: Text(
option.label,
style: const TextStyle(
color: Colors.deepOrange,
),
),
),
)
: SizedBox(
height: 60,
child: Center(
child: Text(
option.label,
style: TextStyle(
color: Colors.orange[700],
),
),
),
),
);
},
),
多选选择字段
以下是一个多选选择字段的示例,包含自定义菜单控制:
import 'package:flutter/material.dart';
import 'package:select_field/select_field.dart';
class MultiSelectOptionsControl<String> extends StatefulWidget {
final List<Option<String>> options;
const MultiSelectOptionsControl({
super.key,
required this.options,
});
@override
State<MultiSelectOptionsControl<String>> createState() =>
_MultiSelectOptionsControlState<String>();
}
class _MultiSelectOptionsControlState<String>
extends State<MultiSelectOptionsControl<String>> {
late final List<Option<String>> initalOptions;
late final MultiSelectFieldMenuController<String> menuController;
void onOptionSelected(List<Option<String>> options) {
setState(() {
menuController.selectedOptions = options;
});
}
void onOptionRemoved(Option<String> option) {
final options = menuController.selectedOptions;
options.remove(option);
setState(() {
menuController.selectedOptions = options;
});
}
void onTapOutside() {
menuController.isExpanded = false;
}
void onTap() {
menuController.isExpanded = !menuController.isExpanded;
}
@override
void initState() {
super.initState();
initalOptions = widget.options.sublist(1, 3);
menuController = MultiSelectFieldMenuController(
isExpanded: true,
initalOptions: initalOptions,
);
}
@override
void dispose() {
menuController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
MultiSelectField<String>(
options: widget.options,
fieldText: 'Select fruit',
onTap: onTap,
onTapOutside: onTapOutside,
onOptionsSelected: onOptionSelected,
menuController: menuController,
menuDecoration: MenuDecoration(
childBuilder: (context, option, isSelected) {
return Row(
children: [
Expanded(
child: Text(
option.label,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.textButtonTheme
.style
?.foregroundColor
?.resolve({}),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Icon(
isSelected
? Icons.check_box_outlined
: Icons.check_box_outline_blank_outlined,
color: Theme.of(context)
.textButtonTheme
.style
?.foregroundColor
?.resolve({}),
),
],
);
},
),
),
Wrap(
spacing: 10,
runSpacing: 20,
children: menuController.selectedOptions
.map(
(option) => Chip(
label: Text(option.label),
onDeleted: () => onOptionRemoved(option),
shape: const StadiumBorder(),
),
)
.toList(),
),
],
);
}
}
完整示例
以下是一个完整的示例,展示了如何在一个应用中使用上述选择字段组件:
import 'package:flutter/material.dart';
import 'package:select_field/select_field.dart';
const fruitOptions = <String>[
'Apple',
'Banana',
'Strawberry',
'Cherry',
'Orange',
'Raspberry',
];
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Select Field',
theme: ThemeData.light(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
final options = fruitOptions
.map((fruit) => Option(label: fruit, value: fruit))
.toList();
return Scaffold(
appBar: AppBar(
title: const Text(
'Search and Select',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
StyledSelectField(options: options),
const SizedBox(height: 32),
CustomMenuSelectField(options: options),
const SizedBox(height: 32),
MultiSelectOptionsControl<String>(options: options),
const SizedBox(height: 32),
SearchSelectField(options: options),
const SizedBox(height: 32),
SearchMultiSelectField(options: options),
],
),
),
);
}
}
class StyledSelectField extends StatelessWidget {
final List<Option<String>> options;
const StyledSelectField({super.key, required this.options});
@override
Widget build(BuildContext context) {
return SelectField<String>(
options: options,
initialOption: Option<String>(
label: fruitOptions[0],
value: fruitOptions[0],
),
menuPosition: MenuPosition.below,
onTextChanged: (value) => debugPrint(value),
onOptionSelected: (option) => debugPrint(option.toString()),
inputStyle: const TextStyle(),
menuDecoration: MenuDecoration(
margin: const EdgeInsets.only(top: 8),
height: 365,
alignment: MenuAlignment.center,
backgroundDecoration: BoxDecoration(
color: Colors.green[100],
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
offset: const Offset(1, 1),
color: Colors.brown[300]!,
blurRadius: 3,
),
],
),
animationDuration: const Duration(milliseconds: 400),
buttonStyle: TextButton.styleFrom(
fixedSize: const Size(double.infinity, 60),
backgroundColor: Colors.green[100],
alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(16),
shape: const RoundedRectangleBorder(),
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.green,
),
),
separatorBuilder: (context, index) => Container(
height: 1,
width: double.infinity,
color: Colors.green,
),
),
);
}
}
class CustomMenuSelectField extends StatelessWidget {
final List<Option<String>> options;
const CustomMenuSelectField({super.key, required this.options});
@override
Widget build(BuildContext context) {
return SelectField<String>(
options: options,
optionBuilder: (context, option, isSelected, onOptionSelected) {
return GestureDetector(
onTap: () => onOptionSelected(option),
child: isSelected
? Container(
height: 60,
color: Colors.deepOrange.withOpacity(0.2),
child: Center(
child: Text(
option.label,
style: const TextStyle(
color: Colors.deepOrange,
),
),
),
)
: SizedBox(
height: 60,
child: Center(
child: Text(
option.label,
style: TextStyle(
color: Colors.orange[700],
),
),
),
),
);
},
);
}
}
class SearchSelectField extends StatelessWidget {
final List<Option<String>> options;
const SearchSelectField({super.key, required this.options});
@override
Widget build(BuildContext context) {
return SelectField<String>(
options: options,
searchable: true,
searchHint: 'Search fruits...',
onTextChanged: (value) => debugPrint(value),
onOptionSelected: (option) => debugPrint(option.toString()),
);
}
}
class SearchMultiSelectField extends StatelessWidget {
final List<Option<String>> options;
const SearchMultiSelectField({super.key, required this.options});
@override
Widget build(BuildContext context) {
return MultiSelectField<String>(
options: options,
searchable: true,
searchHint: 'Search fruits...',
onOptionsSelected: (options) => debugPrint(options.toString()),
);
}
}
以上示例展示了如何在 Flutter 应用中使用 select_field
插件来创建单选和多选选择字段,并自定义下拉菜单的外观和行为。希望这些示例对你有所帮助!更多详细信息可以参考 GitHub 仓库。
更多关于Flutter选择字段插件select_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter选择字段插件select_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用select_field
插件的一个简单示例。select_field
是一个Flutter插件,用于创建带有搜索功能的下拉菜单(选择字段)。
首先,你需要在你的pubspec.yaml
文件中添加select_field
依赖项:
dependencies:
flutter:
sdk: flutter
select_field: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来获取依赖项。
以下是一个完整的Flutter应用示例,展示了如何使用select_field
:
import 'package:flutter/material.dart';
import 'package:select_field/select_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Select Field Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<String> options = [
'Option 1',
'Option 2',
'Option 3',
'Option 4',
'Option 5',
];
String? selectedOption;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Select Field Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
SelectField<String>(
label: 'Choose an option',
hint: 'Select...',
options: options,
onSelected: (value) {
setState(() {
selectedOption = value;
});
},
searchEnabled: true,
clearable: true,
),
SizedBox(height: 20),
Text('Selected Option: ${selectedOption ?? 'None'}'),
],
),
),
);
}
}
代码解释
-
依赖项:在
pubspec.yaml
文件中添加select_field
依赖项。 -
MyApp:主应用类,设置应用的主题和主页。
-
MyHomePage:主页,包含状态(选中的选项)。
-
options:包含下拉选项的列表。
-
selectedOption:存储当前选中的选项。
-
SelectField:
label
:标签,显示在字段上方。hint
:提示文本,显示在没有选中任何选项时。options
:选项列表。onSelected
:当用户选择一个选项时调用的回调函数,用于更新状态。searchEnabled
:启用搜索功能。clearable
:允许用户清除选中项。
-
Text:显示当前选中的选项。
这样,你就可以在你的Flutter应用中使用select_field
插件了。你可以根据需要进一步自定义和扩展这个示例。