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

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

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

在这里插入图片描述

一、TextField源码中的代码contextMenuBuilder

我这里在中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

继承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中使用CustomTextSelectionToolbar

在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

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

猜你喜欢

转载自blog.csdn.net/gloryFlow/article/details/132970840