Flutter自动补全插件elastic_autocomplete的使用
Flutter自动补全插件elastic_autocomplete的使用
ElasticAutocomplete
是一个结合了 Autocomplete
和 LocalStorage
的小部件。通过它,您可以轻松地实现自动补全功能,并且可以将数据存储在本地存储或内存中。
功能
-
它可以通过
ElasticAutocompleteController
轻松处理选项列表,并通过id
共享相同的选项。- 您可以在本地存储中存储数据,这些数据会一直保留,直到用户清理它们。
- 您也可以仅在内存中(类似于会话存储)存储数据,这些数据会一直保留,直到程序终止。
- 在生成候选时,您可以选择是否区分大小写。如果想自己生成候选,可以设置
contains
函数。
-
可以通过
ElasticAutocompleteController
简单生成fieldViewBuilder
和optionsBuilder
。但是,如果不使用控制器,也可以自行设置它们两个。
使用
示例:不使用控制器
您可以使用 optionsBuilder
控制选项列表。此外,还可以自行装饰 TextFormField
。
ElasticAutocomplete<String>(
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<String>.empty();
}
const List<String> options = [
"app",
"bar",
"car"
];
return options.where((String option) {
return option.contains(textEditingValue.text);
});
},
fieldViewBuilder: (BuildContext context,
TextEditingController textEditingController,
FocusNode focusNode,
void Function() onFieldSubmitted) {
return TextFormField(
autofocus: true,
// 必须在textFormField中设置controller, focusNode, 和onFieldSubmitted
controller: textEditingController,
focusNode: focusNode,
onFieldSubmitted: (String value) {
onFieldSubmitted();
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
));
});
示例:使用控制器
使用 ElasticAutocompleteController
加载和设置选项列表非常方便。此外,也容易生成 optionsBuilder
和 fieldViewBuilder
。您可以在 ElasticAutocompleteController
中设置是否区分大小写来影响由控制器自动生成的 optionBuilder
。默认情况下是区分大小写的。
class MyWidgetState extends State<MyWidget> {
final _formKey = GlobalKey<FormState>();
late FocusNode _node;
late ElasticAutocompleteController<String> _elasticAutocompleteCtrl;
late TextEditingController _textEditingCtrl;
[@override](/user/override)
void initState() {
_node = FocusNode();
_textEditingCtrl = TextEditingController();
_elasticAutocompleteCtrl =
ElasticAutocompleteController(id: 'example', caseSensitive: false);
super.initState();
}
[@override](/user/override)
void dispose() {
_textEditingCtrl.dispose();
_node.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElasticAutocomplete<String>(
controller: _elasticAutocompleteCtrl,
// 使用由控制器生成的optionsBuilder
optionsBuilder: _elasticAutocompleteCtrl.optionsBuilder,
// 使用由控制器生成的fieldViewBuilder
fieldViewBuilder: _elasticAutocompleteCtrl.fieldViewBuilder(
decoration: const InputDecoration(
border: OutlineInputBorder(),
)),
// 使用textEditingController获取TextFormField中的值
textEditingController: _textEditingCtrl,
// 设置textEditingController时,同时设置focusNode
focusNode: _node),
// 将新值存储到内存单元中
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
String val = _textEditingCtrl.text;
// 清空文本输入字段
_textEditingCtrl.clear();
// 存储到内存单元
await _elasticAutocompleteCtrl.store(val);
print(val);
}
},
child: const Text("发送")),
// 清除内存单元中的所有选项
ElevatedButton(
onPressed: () {
_elasticAutocompleteCtrl.clear();
},
child: const Text("清除"),
),
],
));
}
}
文档
示例代码
以下是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:elastic_autocomplete/elastic_autocomplete.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// 此小部件是您的应用程序的根
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: const MyHomePage(title: 'ElasticAutocomplete'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Scrollbar(
child: SingleChildScrollView(
padding: const EdgeInsets.all(10),
child: Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 400),
child: const Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 15),
child: Text(
'示例1 构建选项而不使用控制器',
style: TextStyle(fontSize: 18),
)),
Example1(),
Padding(
padding: EdgeInsets.symmetric(vertical: 15),
child: Text(
'示例2 构建选项并使用控制器',
style: TextStyle(fontSize: 18),
)),
Example2(),
Padding(
padding: EdgeInsets.symmetric(vertical: 15),
child: Text(
'示例3 自定义文本输入字段',
style: TextStyle(fontSize: 18),
)),
Example3(),
Padding(
padding: EdgeInsets.symmetric(vertical: 15),
child: Text(
'示例4 与示例2共享相同的存储',
style: TextStyle(fontSize: 18),
)),
Example4(),
],
),
))),
));
}
}
class Example1 extends StatefulWidget {
const Example1({Key? key}) : super(key: key);
[@override](/user/override)
State<Example1> createState() => Example1State();
}
class Example1State extends State<Example1> {
[@override](/user/override)
Widget build(BuildContext context) {
return ElasticAutocomplete(
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<String>.empty();
}
const List<String> options = [
"app",
"bar",
"car",
"dot",
"ear",
"foo",
"god",
"hop",
"ice",
"jam"
];
return options.where((String option) {
return option.contains(textEditingValue.text);
});
}, fieldViewBuilder: (BuildContext context,
TextEditingController textEditingController,
FocusNode focusNode,
void Function() onFieldSubmitted) {
// 自行设计字段视图
return TextFormField(
autofocus: true,
// 必须在textFormField中设置controller, focusNode, 和onFieldSubmitted
controller: textEditingController,
focusNode: focusNode,
onFieldSubmitted: (String value) {
onFieldSubmitted();
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
));
});
}
}
class Example2 extends StatefulWidget {
const Example2({Key? key}) : super(key: key);
[@override](/user/override)
State<Example2> createState() => Example2State();
}
class Example2State extends State<Example2> {
final _formKey = GlobalKey<FormState>();
late FocusNode _node;
late ElasticAutocompleteController<String> _elasticAutocompleteCtrl;
late TextEditingController _textEditingCtrl;
[@override](/user/override)
void initState() {
_node = FocusNode();
_textEditingCtrl = TextEditingController();
_elasticAutocompleteCtrl =
ElasticAutocompleteController(id: 'example2', caseSensitive: false);
super.initState();
}
[@override](/user/override)
void dispose() {
_textEditingCtrl.dispose();
_node.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElasticAutocomplete(
controller: _elasticAutocompleteCtrl,
// 使用由控制器生成的optionsBuilder
optionsBuilder: _elasticAutocompleteCtrl.optionsBuilder,
fieldViewBuilder: _elasticAutocompleteCtrl.fieldViewBuilder(
decoration: const InputDecoration(
border: OutlineInputBorder(),
)),
// 使用textEditingController获取TextFormField中的值
textEditingController: _textEditingCtrl,
// 设置textEditingController时,同时设置focusNode
focusNode: _node,
),
const SizedBox(height: 20),
Row(
children: [
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
String val = _textEditingCtrl.text;
_textEditingCtrl.clear();
await _elasticAutocompleteCtrl.store(val);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Append "$val" to the options')));
}
},
child:
const Text("发送", style: TextStyle(color: Colors.white)),
),
const SizedBox(
width: 10,
),
ElevatedButton(
onPressed: () {
_elasticAutocompleteCtrl.clear();
},
child: const Text("清除",
style: TextStyle(color: Colors.white)),
),
],
)
],
));
}
}
class Example3 extends StatelessWidget {
const Example3({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
ElasticAutocompleteController ctrl = ElasticAutocompleteController(
id: 'example3',
initialOptions: ["apple", "banana", "cat", "dog", "elephant"],
showTopKWhenInputEmpty: 3);
return ElasticAutocomplete(
controller: ctrl,
optionsBuilder: ctrl.optionsBuilder,
fieldViewBuilder: ctrl.fieldViewBuilder(
cursorColor: Colors.green,
style: const TextStyle(color: Colors.green),
decoration: const InputDecoration(
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.search),
hintText: '提示文字')));
}
}
class Example4 extends StatelessWidget {
const Example4({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
ElasticAutocompleteController ctrl = ElasticAutocompleteController(
// 使用与example2相同的id
id: 'example2');
return ElasticAutocomplete(
controller: ctrl,
optionsBuilder: ctrl.optionsBuilder,
fieldViewBuilder: ctrl.fieldViewBuilder(
decoration: const InputDecoration(border: OutlineInputBorder())));
}
}
更多关于Flutter自动补全插件elastic_autocomplete的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自动补全插件elastic_autocomplete的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用elastic_autocomplete
插件来实现自动补全功能的代码示例。这个插件通常用于搜索功能,当用户输入文本时,它会根据输入内容显示建议列表。
首先,确保你已经在pubspec.yaml
文件中添加了elastic_autocomplete
依赖:
dependencies:
flutter:
sdk: flutter
elastic_autocomplete: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个简单的使用示例:
- 导入必要的包:
import 'package:flutter/material.dart';
import 'package:elastic_autocomplete/elastic_autocomplete.dart';
- 定义主应用程序:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Elastic Autocomplete Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SearchScreen(),
);
}
}
- 创建搜索屏幕:
class SearchScreen extends StatefulWidget {
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
final TextEditingController _controller = TextEditingController();
List<String> _suggestions = [
'Apple',
'Banana',
'Orange',
'Grape',
'Pineapple',
'Strawberry',
'Blueberry',
// 添加更多建议项
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Elastic Autocomplete Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Search...',
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: () {
_controller.clear();
},
),
),
onChanged: (value) {
// 当用户输入文本时触发
setState(() {}); // 触发UI更新以显示新的建议列表
},
),
SizedBox(height: 16),
Expanded(
child: _buildSuggestionList(),
),
],
),
),
);
}
Widget _buildSuggestionList() {
final String query = _controller.text.toLowerCase();
final List<String> filteredSuggestions = _suggestions
.where((suggestion) =>
suggestion.toLowerCase().contains(query))
.toList();
return ElasticAutocomplete(
suggestions: filteredSuggestions,
onSuggestionSelected: (String suggestion) {
_controller.value = _controller.value.copyWith(
text: suggestion,
selection: TextSelection.fromPosition(
TextPosition(
affinity: TextAffinity.downstream,
offset: suggestion.length,
),
),
composing: TextRange.empty,
);
},
builder: (context, suggestions) {
return ListView.builder(
itemCount: suggestions.length,
itemBuilder: (context, index) {
final String suggestion = suggestions[index];
return ListTile(
leading: Icon(Icons.search),
title: Text(suggestion),
onTap: () {
// 当用户点击建议项时触发
_controller.text = suggestion;
},
);
},
);
},
);
}
}
在这个示例中,我们创建了一个简单的搜索屏幕,其中包含一个TextField
用于用户输入,以及一个使用ElasticAutocomplete
小部件显示的建议列表。当用户输入文本时,_buildSuggestionList
函数会根据输入内容过滤建议列表,并更新UI。当用户选择一个建议时,该建议会被填充到TextField
中。
注意:elastic_autocomplete
的具体API和用法可能会随着版本的更新而有所变化,因此请参考最新的官方文档和示例代码以获取最准确的信息。