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

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

相关推荐
SoraLuna1 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
lqj_本人3 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人6 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
起司锅仔11 小时前
Flutter启动流程(2)
flutter
martian66512 小时前
QT开发:掌握现代UI动画技术:深入解析QML和Qt Quick中的动画效果
开发语言·c++·qt·ui
hello world smile14 小时前
最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
android·前端·javascript·flutter·dart·yaml·pubspec.yaml
lqj_本人14 小时前
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
flutter·harmonyos
iFlyCai14 小时前
极简实现酷炫动效:Flutter隐式动画指南第二篇之一些酷炫的隐式动画效果
flutter
lqj_本人14 小时前
Flutter&鸿蒙next 中使用 MobX 进行状态管理
flutter·华为·harmonyos
初九之潜龙勿用14 小时前
C#结合JS解决Word添加无效位图导致进程停滞的问题
javascript·ui·c#·word·asp.net