简体   繁体   中英

How to have a custom context menu for TextFields in Flutter?

The flutter (on desktop) shows this custom context menu for the text fields which is absolutely ugly:

Do you know of a way that this can be customized?

UPDATE

I actually found the answer. You have to implement a class based on TextSelectionControls and give it to selectionControls of the TextInputField. Also you can lookup the MaterialTextSelectionControls which has a simple implementation to understand how it is done.

With Flutter 3.7 you can now create custom context menus anywhere in a Flutter app.

A contextMenuBuilder parameter has been added to many widgets (eg TextField , CupertinoTextField , SelectionArea , etc.). You can return any widget you want from contextMenuBuilder , including modifying the default platform-adaptive context menu.

Example: ( source )

TextField(
  contextMenuBuilder: (context, editableTextState) {
    final TextEditingValue value = editableTextState.textEditingValue;
    final List<ContextMenuButtonItem> buttonItems = editableTextState.contextMenuButtonItems;
    if (isValidEmail(value.selection.textInside(value.text))) {
      buttonItems.insert(
          0,
          ContextMenuButtonItem(
            label: 'Send email',
            onPressed: () {
              ContextMenuController.removeAny();
              Navigator.of(context).push(_showDialog(context));
            },
          ));
    }
    return AdaptiveTextSelectionToolbar.buttonItems(
      anchors: editableTextState.contextMenuAnchors,
      buttonItems: buttonItems,
    );
  },
)

This new feature works outside of text selection too by using ContextMenuController . You could, for example, create an Image widget that shows a Save button when right clicked or long pressed: ( source ) 上下文菜单控制器

ContextMenuRegion(
  contextMenuBuilder: (context, offset) {
    return AdaptiveTextSelectionToolbar.buttonItems(
      anchors: TextSelectionToolbarAnchors(
        primaryAnchor: offset,
      ),
      buttonItems: <ContextMenuButtonItem>[
        ContextMenuButtonItem(
          onPressed: () {
            ContextMenuController.removeAny();
            Navigator.of(context).push(_showDialog(context));
          },
          label: 'Save',
        ),
      ],
    );
  },
  child: const SizedBox(
    width: 200.0,
    height: 200.0,
    child: FlutterLogo(),
  ),
)

You can find more examples of custom context menus in:

Answer for 2023

This functionality was added in Flutter 3.7 ( related Github comment ).

class CustomMenuPage extends StatelessWidget {
  CustomMenuPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SizedBox(
          width: 300.0,
          child: TextField(
            maxLines: 4,
            minLines: 2,
            contextMenuBuilder: (context, editableTextState) {
              return _MyContextMenu(
                anchor: editableTextState.contextMenuAnchors.primaryAnchor,
                children: [
                  TextSelectionToolbarTextButton(
                    padding: EdgeInsets.all(8),
                    onPressed: () {
                      debugPrint('Flutter');
                    },
                    child: Text('Flutter is cool'),
                  )
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

class _MyContextMenu extends StatelessWidget {
  const _MyContextMenu({
    required this.anchor,
    required this.children,
  });

  final Offset anchor;
  final List<Widget> children;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          top: anchor.dy,
          left: anchor.dx,
          child: Card(
            child: Column(
              children: children,
            ),
          ),
        ),
      ],
    );
  }
}

在此处输入图像描述

See the official context menu sample repo here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM