Flutter增强文本输入功能插件extended_text_field的使用
Flutter增强文本输入功能插件extended_text_field的使用
概述
extended_text_field
是Flutter官方TextField组件的一个第三方扩展库,它提供了丰富的功能来创建特殊文本(如内联图片、@somebody、自定义背景等),并且支持快速构建富文本、自定义选择工具栏和句柄。
Web demo for ExtendedTextField
主要特性对比
Feature | ExtendedTextField | TextField |
---|---|---|
内联图片和文本混合 | 支持,允许显示内联图片和混合文本 | 仅支持显示文本,但有文本选择问题 |
复制实际值 | 支持,启用复制文本的实际值 | 不支持 |
快速构建富文本 | 支持,基于文本格式快速构建富文本 | 不支持 |
使用方法
添加依赖
在pubspec.yaml
文件中添加以下依赖:
dependencies:
extended_text_field: ^11.0.1-ohos
示例代码
基本用法
import 'package:flutter/material.dart';
import 'package:extended_text_field/extended_text_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Extended Text Field Example')),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ExtendedTextField(
controller: TextEditingController(),
decoration: InputDecoration(
labelText: 'Enter text',
border: OutlineInputBorder(),
),
specialTextSpanBuilder: MySpecialTextSpanBuilder(),
),
),
),
);
}
}
class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
@override
TextSpan build(String data, {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
var textSpan = super.build(data, textStyle: textStyle, onTap: onTap);
return textSpan;
}
@override
SpecialText? createSpecialText(String flag, {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap, int? index}) {
if (flag == null || flag.isEmpty) return null;
if (isStart(flag, AtText.flag)) {
return AtText(textStyle, onTap,
start: index! - (AtText.flag.length - 1),
showAtBackground: true);
} else if (isStart(flag, EmojiText.flag)) {
return EmojiText(textStyle, start: index! - (EmojiText.flag.length - 1));
} else if (isStart(flag, DollarText.flag)) {
return DollarText(textStyle, onTap,
start: index! - (DollarText.flag.length - 1));
}
return null;
}
}
class AtText extends SpecialText {
static const String flag = "@";
final bool showAtBackground;
AtText(TextStyle? textStyle, SpecialTextGestureTapCallback? onTap,
{required this.showAtBackground, required int start})
: super(flag, " ", textStyle, onTap: onTap);
@override
InlineSpan finishText() {
TextStyle textStyle =
this.textStyle?.copyWith(color: Colors.blue, fontSize: 16.0);
final String atText = toString();
return showAtBackground
? BackgroundTextSpan(
background: Paint()..color = Colors.blue.withOpacity(0.15),
text: atText,
actualText: atText,
start: start,
///caret can move into special text
deleteAll: true,
style: textStyle,
recognizer: (TapGestureRecognizer()
..onTap = () {
if (onTap != null) onTap(atText);
}))
: SpecialTextSpan(
text: atText,
actualText: atText,
start: start,
style: textStyle,
recognizer: (TapGestureRecognizer()
..onTap = () {
if (onTap != null) onTap(atText);
}));
}
}
内联图片
import 'package:flutter/material.dart';
import 'package:extended_text_field/extended_text_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Inline Image Example')),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ExtendedTextField(
controller: TextEditingController(),
decoration: InputDecoration(
labelText: 'Enter text with inline images',
border: OutlineInputBorder(),
),
specialTextSpanBuilder: MySpecialTextSpanBuilder(),
),
),
),
);
}
}
class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder {
@override
TextSpan build(String data, {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap}) {
var textSpan = super.build(data, textStyle: textStyle, onTap: onTap);
return textSpan;
}
@override
SpecialText? createSpecialText(String flag, {TextStyle? textStyle, SpecialTextGestureTapCallback? onTap, int? index}) {
if (flag == null || flag.isEmpty) return null;
if (isStart(flag, "[img]")) {
return ImageTextSpan(textStyle, onTap,
start: index! - ("[img]".length - 1),
imageProvider: AssetImage("assets/image.png"));
}
return null;
}
}
class ImageTextSpan extends SpecialText {
final ImageProvider imageProvider;
ImageTextSpan(TextStyle? textStyle, SpecialTextGestureTapCallback? onTap,
{required this.imageProvider, required int start})
: super("[img]", "", textStyle, onTap: onTap);
@override
InlineSpan finishText() {
return ImageSpan(
imageProvider,
imageWidth: 24.0,
imageHeight: 24.0,
margin: EdgeInsets.only(left: 2.0, bottom: 0.0, right: 2.0),
start: start,
actualText: "[img]",
);
}
}
自定义选择工具栏
import 'package:flutter/material.dart';
import 'package:extended_text_field/extended_text_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Custom Toolbar Example')),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ExtendedTextField(
controller: TextEditingController(),
decoration: InputDecoration(
labelText: 'Enter text',
border: OutlineInputBorder(),
),
selectionControls: MyTextSelectionControls(),
),
),
),
);
}
}
class MyTextSelectionControls extends MaterialTextSelectionControls {
@override
Size getHandleSize(double textLineHeight) => Size(22.0, 22.0);
@override
Widget buildToolbar(
BuildContext context,
RenderBox renderBox,
Offset globalEditableRegionOffset,
double textLineHeight,
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier? clipboardStatus,
Offset? lastSecondaryTapDownPosition,
) {
return AdaptiveTextSelectionToolbar.editableText(
editableTextState: delegate as ExtendedEditableTextState,
);
}
}
注意事项
- 不支持 RTL 文本方向:当
TextDirection.rtl
时,不会处理特殊文本,且图片位置计算可能会有问题。 - 不支持隐藏文本:当
obscureText
为true
时,不会处理特殊文本。
通过以上内容,您可以快速上手并充分利用 extended_text_field
插件的强大功能。希望这些示例能帮助您更好地理解和使用该插件!
更多关于Flutter增强文本输入功能插件extended_text_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter增强文本输入功能插件extended_text_field的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 extended_text_field
插件来增强 Flutter 文本输入功能的代码示例。extended_text_field
是一个功能强大的 Flutter 插件,它扩展了默认的 TextField
小部件,提供了更多自定义和高级功能,比如自定义文本样式、正则表达式验证、点击链接等。
首先,确保你已经在 pubspec.yaml
文件中添加了 extended_text_field
依赖:
dependencies:
flutter:
sdk: flutter
extended_text_field: ^x.y.z # 替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来是一个简单的示例,展示如何使用 ExtendedTextField
来创建一个带有正则表达式验证和自定义样式的文本输入字段:
import 'package:flutter/material.dart';
import 'package:extended_text_field/extended_text_field.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('ExtendedTextField Example'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: CustomTextField(),
),
),
),
);
}
}
class CustomTextField extends StatefulWidget {
@override
_CustomTextFieldState createState() => _CustomTextFieldState();
}
class _CustomTextFieldState extends State<CustomTextField> {
final TextEditingController _controller = TextEditingController();
final FocusNode _focusNode = FocusNode();
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ExtendedTextField(
controller: _controller,
focusNode: _focusNode,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter text with regex validation',
helperText: 'Only alphabets and numbers are allowed',
),
maxLength: 20,
maxLengthEnforced: true,
specialText: SpecialText.all(
regex: RegExp(r'[^a-zA-Z0-9]'),
style: TextStyle(color: Colors.red, decoration: TextDecoration.underline),
start: 0,
),
onChanged: (text) {
// Handle text changes if needed
print('Current text: $text');
},
onSubmitted: (text) {
// Handle text submission if needed
print('Submitted text: $text');
},
validator: (text) {
if (!RegExp(r'^[a-zA-Z0-9]*$').hasMatch(text)) {
return 'Only alphabets and numbers are allowed';
}
return null;
},
);
}
}
在这个示例中,我们做了以下几件事:
-
创建
ExtendedTextField
:- 使用
TextEditingController
和FocusNode
来控制文本输入和焦点。 - 设置输入装饰(
InputDecoration
),包括边框、标签文本和辅助文本。
- 使用
-
正则表达式验证:
- 使用
SpecialText.all
来标记不符合正则表达式的文本(这里是不符合[a-zA-Z0-9]
的字符),并为这些字符设置特定的样式(红色下划线)。 - 使用
validator
回调函数在表单提交时进行验证,如果不符合正则表达式,返回错误信息。
- 使用
-
事件处理:
- 使用
onChanged
回调函数处理文本变化事件。 - 使用
onSubmitted
回调函数处理文本提交事件。
- 使用
这个示例展示了如何使用 extended_text_field
插件来增强文本输入功能,包括自定义样式、正则表达式验证等。你可以根据具体需求进一步自定义和扩展这个示例。