flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单AdaptiveTextSelectionToolba样式UI效果

flutter开发实战-自定义长按TextField输入框剪切、复制、选择全部菜单样式UI效果

在开发过程中,需要长按TextField输入框cut、copy设置为中文"复制、粘贴",我首先查看了TextField中的源码,看到了ToolbarOptions、AdaptiveTextSelectionToolbar,这时候我们可以在剪切、复制、选择全部菜单样式UI效果上显示icon的按钮了。

一、TextField源码中的代码contextMenuBuilder

我这里在中TextField中的源码,看到了ToolbarOptions、AdaptiveTextSelectionToolbar,可以继承AdaptiveTextSelectionToolbar来实现更改剪切、复制、选择全部菜单样式效果

将自定义的AdaptiveTextSelectionToolbar,设置到contextMenuBuilder即可。

TextField源码一段

dart 复制代码
  /// {@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

继承AdaptiveTextSelectionToolbar实现自定义的toolbar样式CustomTextSelectionToolbar

自定义后需要实现按钮列表

dart 复制代码
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的按钮样式

dart 复制代码
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;

  @override
  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完整代码如下

dart 复制代码
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);

  @override
  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;

  @override
  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中使用CustomTextSelectionToolbar

在TextField输入框中设置contextMenuBuilder

dart 复制代码
static Widget _textFieldContextMenuBuilder(BuildContext context, EditableTextState editableTextState) {
    return CustomTextSelectionToolbar.editableText(
      editableTextState: editableTextState,
    );
  }

最后在TextField输入框中设置contextMenuBuilder

dart 复制代码
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

学习记录,每天不停进步。

相关推荐
syj_1111 小时前
初识ArkUI
ui·arkts·arkui
芋芋qwq9 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
比格丽巴格丽抱9 小时前
flutter项目苹果编译运行打包上线
flutter·ios
SoaringHeart9 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
鸿蒙自习室10 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
大霞上仙13 小时前
element ui table 每行不同状态
vue.js·ui·elementui
AiFlutter14 小时前
Flutter通过 Coap发送组播
flutter
栈老师不回家21 小时前
Element UI 组件库详解【Vue】
前端·vue.js·ui
郭梧悠1 天前
HarmonyOS(57) UI性能优化
ui·性能优化·harmonyos
wyh要好好学习1 天前
WPF数据加载时添加进度条
ui·wpf