flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单样式UI效果
在开发过程中,需要长按TextField输入框cut、copy设置为中文“复制、粘贴”,我首先查看了TextField中的源码,看到了ToolbarOptions、AdaptiveTextSelectionToolbar,这时候我们可以在剪切、复制、选择全部菜单样式UI效果上显示icon的按钮了。
我这里在中TextField中的源码,看到了ToolbarOptions、AdaptiveTextSelectionToolbar,可以继承AdaptiveTextSelectionToolbar来实现更改剪切、复制、选择全部菜单样式效果
将自定义的AdaptiveTextSelectionToolbar,设置到contextMenuBuilder即可。
TextField源码一段
/// {@macro flutter.widgets.EditableText.contextMenuBuilder}
///
/// If not provided, will build a default menu based on the platform.
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar], which is built by default.
final EditableTextContextMenuBuilder? contextMenuBuilder;
static Widget _defaultContextMenuBuilder(BuildContext context, EditableTextState editableTextState) {
return AdaptiveTextSelectionToolbar.editableText(
editableTextState: editableTextState,
);
}
继承AdaptiveTextSelectionToolbar实现自定义的toolbar样式CustomTextSelectionToolbar
自定义后需要实现按钮列表
List<Widget> resultChildren = <Widget>[];
for (int i = 0; i < buttonItems!.length; i++) {
final ContextMenuButtonItem buttonItem = buttonItems![i];
resultChildren.add(SelectionToolBarButton(
width: 100,
height: 50,
icon: (i == 0)?Icon(
Icons.cut,
color: Colors.white,
size: 14,
):Icon(
Icons.copy,
color: Colors.white,
size: 16,
),
title: getButtonLabelString(context, buttonItem),
onPressed: buttonItem.onPressed,
));
}
自定义按钮SelectionToolBarButton,设置icon+title的按钮样式
class SelectionToolBarButton extends StatelessWidget {
const SelectionToolBarButton({
super.key,
required this.width,
required this.height,
required this.icon,
required this.title,
required this.onPressed,
});
final double width;
final double height;
final Icon icon;
final String title;
final VoidCallback onPressed;
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
onPressed();
},
child: Container(
color: Colors.black87,
width: width,
height: height,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
icon,
SizedBox(
width: 5,
),
Text(
title,
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
],
),
),
);
}
}
CustomTextSelectionToolbar完整代码如下
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CustomTextSelectionToolbar extends AdaptiveTextSelectionToolbar {
const CustomTextSelectionToolbar(
{super.key, required super.children, required super.anchors});
CustomTextSelectionToolbar.editableText({
super.key,
required EditableTextState editableTextState,
}) : super.editableText(editableTextState: editableTextState);
Widget build(BuildContext context) {
// If there aren't any buttons to build, build an empty toolbar.
if ((children != null && children!.isEmpty) ||
(buttonItems != null && buttonItems!.isEmpty)) {
return const SizedBox.shrink();
}
List<Widget> resultChildren = <Widget>[];
for (int i = 0; i < buttonItems!.length; i++) {
final ContextMenuButtonItem buttonItem = buttonItems![i];
resultChildren.add(SelectionToolBarButton(
width: 100,
height: 50,
icon: (i == 0)?Icon(
Icons.cut,
color: Colors.white,
size: 14,
):Icon(
Icons.copy,
color: Colors.white,
size: 16,
),
title: getButtonLabelString(context, buttonItem),
onPressed: buttonItem.onPressed,
));
}
switch (Theme.of(context).platform) {
case TargetPlatform.iOS:
return CupertinoTextSelectionToolbar(
anchorAbove: anchors.primaryAnchor,
anchorBelow: anchors.secondaryAnchor == null
? anchors.primaryAnchor
: anchors.secondaryAnchor!,
children: resultChildren,
);
case TargetPlatform.android:
return TextSelectionToolbar(
anchorAbove: anchors.primaryAnchor,
anchorBelow: anchors.secondaryAnchor == null
? anchors.primaryAnchor
: anchors.secondaryAnchor!,
children: resultChildren,
);
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
return DesktopTextSelectionToolbar(
anchor: anchors.primaryAnchor,
children: resultChildren,
);
case TargetPlatform.macOS:
return CupertinoDesktopTextSelectionToolbar(
anchor: anchors.primaryAnchor,
children: resultChildren,
);
}
}
/// Returns the default button label String for the button of the given
/// [ContextMenuButtonType] on any platform.
static String getButtonLabelString(BuildContext context, ContextMenuButtonItem buttonItem) {
if (buttonItem.label != null) {
return buttonItem.label!;
}
switch (Theme.of(context).platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
assert(debugCheckHasMaterialLocalizations(context));
switch (buttonItem.type) {
case ContextMenuButtonType.cut:
return "剪切";
case ContextMenuButtonType.copy:
return "复制";
case ContextMenuButtonType.paste:
return "粘贴";
case ContextMenuButtonType.selectAll:
return "选择全部";
case ContextMenuButtonType.custom:
return '';
}
}
}
}
class SelectionToolBarButton extends StatelessWidget {
const SelectionToolBarButton({
super.key,
required this.width,
required this.height,
required this.icon,
required this.title,
required this.onPressed,
});
final double width;
final double height;
final Icon icon;
final String title;
final VoidCallback onPressed;
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
onPressed();
},
child: Container(
color: Colors.black87,
width: width,
height: height,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
icon,
SizedBox(
width: 5,
),
Text(
title,
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
],
),
),
);
}
}
在TextField输入框中设置contextMenuBuilder
static Widget _textFieldContextMenuBuilder(BuildContext context, EditableTextState editableTextState) {
return CustomTextSelectionToolbar.editableText(
editableTextState: editableTextState,
);
}
最后在TextField输入框中设置contextMenuBuilder
TextField(
contextMenuBuilder: _textFieldContextMenuBuilder,
minLines: 1,
maxLines: null,
keyboardType: TextInputType.multiline,
textAlignVertical: TextAlignVertical.center,
autofocus: widget.autofocus,
focusNode: editFocusNode,
controller: widget.textEditingController,
textInputAction: TextInputAction.send,
)
至此可以自定义长按TextField输入框剪切、复制、选择全部菜单样式UI效果
使用系统全局剪切、复制、选择全部设置为中文,可以查看:https://blog.csdn.net/gloryFlow/article/details/132966717
flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单样式UI效果。自定义AdaptiveTextSelectionToolbar,在TextField输入框中设置contextMenuBuilder,实现功能。
内容较多,描述可能不准确,请见谅。
本文地址:https://blog.csdn.net/gloryFlow/article/details/132970840
学习记录,每天不停进步。