showButtonMenu method

void showButtonMenu()

A method to show a popup menu with the items supplied to PopupMenuButton.itemBuilder at the position of your PopupMenuButton.

By default, it is called when the user taps the button and PopupMenuButton.enabled is set to true. Moreover, you can open the button by calling the method manually.

You would access your PopupMenuButtonState using a GlobalKey and show the menu of the button with globalKey.currentState.showButtonMenu.

Implementation

void showButtonMenu() {
  final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
  final RenderBox button = context.findRenderObject()! as RenderBox;
  final RenderBox overlay = Navigator.of(
    context,
    rootNavigator: widget.useRootNavigator,
  ).overlay!.context.findRenderObject()! as RenderBox;
  final PopupMenuPosition popupMenuPosition = widget.position ?? popupMenuTheme.position ?? PopupMenuPosition.over;
  late Offset offset;
  switch (popupMenuPosition) {
    case PopupMenuPosition.over:
      offset = widget.offset;
    case PopupMenuPosition.under:
      offset = Offset(0.0, button.size.height) + widget.offset;
      if (widget.child == null) {
        // Remove the padding of the icon button.
        offset -= Offset(0.0, widget.padding.vertical / 2);
      }
  }
  final RelativeRect position = RelativeRect.fromRect(
    Rect.fromPoints(
      button.localToGlobal(offset, ancestor: overlay),
      button.localToGlobal(button.size.bottomRight(Offset.zero) + offset, ancestor: overlay),
    ),
    Offset.zero & overlay.size,
  );
  final List<PopupMenuEntry<T>> items = widget.itemBuilder(context);
  // Only show the menu if there is something to show
  if (items.isNotEmpty) {
    widget.onOpened?.call();
    showMenu<T?>(
      context: context,
      elevation: widget.elevation ?? popupMenuTheme.elevation,
      shadowColor: widget.shadowColor ?? popupMenuTheme.shadowColor,
      surfaceTintColor: widget.surfaceTintColor ?? popupMenuTheme.surfaceTintColor,
      items: items,
      initialValue: widget.initialValue,
      position: position,
      shape: widget.shape ?? popupMenuTheme.shape,
      menuPadding: widget.menuPadding ?? popupMenuTheme.menuPadding,
      color: widget.color ?? popupMenuTheme.color,
      constraints: widget.constraints,
      clipBehavior: widget.clipBehavior,
      useRootNavigator: widget.useRootNavigator,
      popUpAnimationStyle: widget.popUpAnimationStyle,
      routeSettings: widget.routeSettings,
    )
    .then<void>((T? newValue) {
      if (!mounted) {
        return null;
      }
      if (newValue == null) {
        widget.onCanceled?.call();
        return null;
      }
      widget.onSelected?.call(newValue);
    });
  }
}