skip to Main Content

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.

2

Answers


  1. 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 (e.g. 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)
    ContextMenuController

    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:

    Login or Signup to reply.
  2. 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,
                ),
              ),
            ),
          ],
        );
      }
    }
    

    enter image description here

    See the official context menu sample repo here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search