Flutter标签管理插件flutter_taggable的使用
Flutter标签管理插件flutter_taggable的使用
允许用户提及其他用户、插入话题标签以及其他实体的标签。此轻量级包提供了一种数据库友好的格式,便于存储和解析标签。该包高度可定制,并且可以与标准的TextField
小部件一起使用。
动机
许多包允许在文本字段中提及或标记用户,但并非所有包都能以一种便于检索和解析的方式来存储这些标签。考虑以下场景:
用户在评论中写入并发布“@Ada Lovelace, 检查一下这个包!”假设后端服务器需要解析这条评论来向Ada发送通知。如果将评论原样存储,会出现两个问题:
- 标签在哪里结束?是
[@Ada](/user/Ada)
、[@Ada](/user/Ada) Lovelace
还是[@Ada](/user/Ada) Lovelace, 检查
?很难确定确切的标签。- 如果Ada更改了她的用户名为
[@Ada](/user/Ada) King
,则评论将不再提及她。
然而,任何可标记的实体通常都有一个唯一标识符,例如用户ID。此包允许标记用户,使得前端显示对用户友好,同时提供一种数据库友好的格式,便于轻松解析和检索。
特性
- 轻量级:此包可以与标准的
TextField
小部件一起使用——你只需将TextEditingController
替换为TagTextEditingController
。 - 对终端用户友好:控制器处理标记逻辑,因此你可以专注于UI。例如,退格键删除整个标签,而不是仅删除一个字符。
- 可定制的标签格式:指定前端格式(如
[@Ada](/user/Ada) Lovelace
)和后端格式(如@123
)。此包还可以支持多种类型的标记(如[@Ada](/user/Ada) Lovelace
和#MyTrendingTopic
,参见上面的视频)。 - 可定制的搜索功能:指定包应如何搜索标签,以及选项应如何显示。
- 类型注解:给
TagTextEditingController
添加类型以提高类型安全性和代码完成度,当你定义回调时。
开始使用
该包假定你的‘可标记’数据有三种形式:
- 代表可标记实体的数据类对象。
- 可以在UI中显示的此实体表示形式。
- 可以存储在数据库中的此实体表示形式。
在示例中,我们使用以下类来表示一个可标记实体:
class Taggable {
const Taggable({required this.id, required this.name, required this.icon});
final String id;
final String name;
final IconData icon;
}
id
是可标记实体的唯一标识符,name
是在UI中显示的字符串。将其与WhatsApp进行比较,可标记实体将是用户,id
将是用户的电话号码,name
将是用户的名字。
该包支持具有多种类型的可标记实体。为了使代码更简洁,我们建议为每种类型的可标记实体创建一个扩展Taggable
的类。例如:
class User extends Taggable {
const User(
{required super.id, required super.name, super.icon = Icons.person});
}
class Topic extends Taggable {
const Topic(
{required super.id, required super.name, super.icon = Icons.topic});
}
或者,您可以使Taggable
类具有返回前端和后端表示形式的抽象方法,由子类实现。
使用
安装
通过以下命令将包添加到项目中:
flutter pub add flutter_taggable
基本用法
要使用该包,你需要将默认的TextEditingController
替换为TagTextEditingController
并指定几个参数;
import 'package:flutter/material.dart';
import 'package:flutter_taggable/flutter_taggable.dart';
class TaggableExample extends StatefulWidget {
@override
_TaggableExampleState createState() => _TaggableExampleState();
}
class _TaggableExampleState extends State<TaggableExample> {
late TagTextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TagTextEditingController<Taggable>(
searchTaggables: searchTaggables,
buildTaggables: buildTaggables,
toFrontendConverter: (taggable) => taggable.name,
toBackendConverter: (taggable) => taggable.id,
tagStyles: {
'@': const TextStyle(color: Colors.blue),
'#': const TextStyle(color: Colors.green),
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Taggable Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Type @ to tag a user or # to tag a topic',
),
),
),
);
}
}
注意如何将控制器类型注解为Taggable
类。创建TagTextEditingController
时需要指定多个参数。展开以下部分了解更多信息。
参数
FutureOr<Iterable<T>> Function(String prefix, String? query) searchTaggables
此函数在用户输入标签时被调用。它应该返回匹配查询的可标记实体列表。prefix
参数是用户开始标签所键入的字符,query
参数是用户在前缀后键入的文本。例如,如果用户键入[@Ada](/user/Ada)
,prefix
将是@
,query
将是Ada
。返回类型为FutureOr
是因为该函数可以是同步的(如果数据已经可用),也可以是异步的(如果数据需要从某个地方获取)。
Future<T?> Function(FutureOr<Iterable<T>> taggables) buildTaggables
此函数接受匹配查询的可标记实体列表,并构建这些实体的UI表示形式。在示例中,使用OverlayEntry
来将选项显示为列表。因为用户通常通过点击选择选项,所以返回类型是一个Future
。示例使用Completer
来返回所选的可标记实体,因为OverlayEntry
不直接返回值。
String Function(T taggable) toFrontendConverter
此函数将可标记实体转换为将在UI中显示的字符串。在示例中,我们使用Taggable
类的name
字段。
String Function(T taggable) toBackendConverter
此函数将可标记实体转换为将在数据库中存储的字符串。在示例中,我们使用Taggable
类的id
字段。
List<TagStyle> tagStyles
此列表指定了用户可以标记实体的方式。每个TagStyle
对象有一个用于触发标记的prefix
(默认为@
),以及一个指定文本字段中标记TextStyle
的style
。此外,它还有一个regExp
参数,用于指定可以在文本字段中找到标记的正则表达式。任何紧跟在prefix
之后且匹配regExp
的字符串都将被视为标记。
转换
在以下三个过程中,可标记实体会被转换:
- 保存带有标签的文本:当需要保存包含标签的文本时,可以使用
TagTextEditingController
的textInBackendFormat
获取器来获取后端格式的文本。不要使用text
获取器,因为内部文本表示形式与前端和后端格式都不相同。 - 填充文本字段:当你有一段文本处于后端格式并希望用它填充文本字段时,可以使用
TagTextEditingController
的setInitialText
方法。除了文本外,还需要提供将后端格式转换为可标记实体的backendToTaggable
函数。此函数具有以下签名:
FutureOr<T?> Function(String prefix, String backendString) backendToTaggable
更多关于Flutter标签管理插件flutter_taggable的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter标签管理插件flutter_taggable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用flutter_taggable
插件的一个基本示例。这个插件允许你轻松地在应用中实现标签管理功能。
首先,你需要在你的pubspec.yaml
文件中添加flutter_taggable
依赖:
dependencies:
flutter:
sdk: flutter
flutter_taggable: ^最新版本号 # 请替换为当前最新版本号
然后运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中,你可以按照以下步骤使用flutter_taggable
:
- 导入包:
在你的Dart文件中导入flutter_taggable
包:
import 'package:flutter_taggable/flutter_taggable.dart';
- 创建标签数据:
定义你想要显示的标签数据。这里我们用一个简单的字符串列表来模拟标签:
List<String> tags = ['Flutter', 'Dart', 'Mobile Development', 'Cross-Platform'];
- 使用TagContainer小部件:
在你的UI中使用TagContainer
小部件来显示和管理标签。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:flutter_taggable/flutter_taggable.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Taggable Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TagPage(),
);
}
}
class TagPage extends StatefulWidget {
@override
_TagPageState createState() => _TagPageState();
}
class _TagPageState extends State<TagPage> {
List<String> tags = ['Flutter', 'Dart', 'Mobile Development', 'Cross-Platform'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Taggable Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TagContainer(
tags: tags,
onDeleted: (tag) {
setState(() {
tags.remove(tag);
});
},
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.grey[200],
),
textStyle: TextStyle(color: Colors.black),
alignment: WrapAlignment.start,
spacing: 4.0,
runSpacing: 4.0,
deleteIcon: Icon(
Icons.close,
color: Colors.red,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 这里可以添加添加新标签的逻辑
setState(() {
tags.add('New Tag'); // 简单示例:添加一个新标签
});
},
tooltip: 'Add Tag',
child: Icon(Icons.add),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个TagContainer
小部件来显示标签。当用户点击删除图标时,标签会从列表中移除。同时,我们提供了一个浮动操作按钮(FAB),用于添加新标签(在这个例子中,只是简单地添加了一个静态的新标签字符串)。
你可以根据自己的需求进一步自定义标签的样式、添加逻辑等。希望这个示例能帮助你开始使用flutter_taggable
插件!