CNContextMenu class

Opens a native context menu for its child: a secondary click (right click, two-finger click) or a Control-click on macOS, a long press on iOS.

The menu is built from the same entries as CNPopupMenuButton — CNPopupMenuItem (icon, subtitle, checked, destructive, disabled), CNPopupMenuDivider and CNPopupMenuSubmenu — and reports the chosen item's path to onSelected, as CNPopupMenuButton.onPathSelected does: [2] is items[2], [3, 1] the second entry of the submenu at items[3]. Dividers count in every index.

  • macOS: an NSMenu opens with its top-left corner at the pointer, as every context menu on the Mac does. SF Symbol icons stay visible on macOS 27, which otherwise hides menu item images. Destructive items are drawn in the system red.
  • iOS 17.4+: a long press opens the system UIMenu from the point that was pressed (a secondary click with a pointer does too), with Liquid Glass on iOS 26. Below iOS 17.4, which cannot open a menu without a touch on its own button, the menu is shown as a CupertinoActionSheet. With showsPreview (any iOS) the long press instead lifts a preview of the child above the dimmed screen, as a system context menu does.
  • Other platforms: the CupertinoActionSheet fallback of CNPopupMenuButton, opened by a long press or a secondary click.
CNContextMenu(
  items: const [
    CNPopupMenuItem(label: 'Copy', icon: CNSymbol('doc.on.doc')),
    CNPopupMenuItem(
      label: 'Share',
      subtitle: 'AirDrop, Messages, Mail',
      icon: CNSymbol('square.and.arrow.up'),
    ),
    CNPopupMenuDivider(),
    CNPopupMenuItem(
      label: 'Delete',
      icon: CNSymbol('trash'),
      isDestructive: true,
    ),
  ],
  onSelected: (path) => debugPrint('chose $path'),
  child: const PhotoTile(),
)

The child keeps its own gestures: a tap still reaches a button inside it. On iOS, screen readers get the menu as the child's long-press action (VoiceOver: double-tap and hold), opened at the child's centre. On macOS VoiceOver cannot open it: Flutter's macOS embedder exposes no "show menu" action. Offer the same commands another way, such as a CNPopupMenuButton, where VoiceOver users need them.

Inheritance
Available extensions

Constructors

CNContextMenu({Key? key, required List<CNPopupMenuEntry> items, required ValueChanged<List<int>> onSelected, required Widget child, bool enabled = true, bool enableHapticFeedback = true, bool showsPreview = false, double previewCornerRadius = 12})
Creates a native context menu region around child.
const

Properties

child → Widget
The region that opens the menu.
final
enabled → bool
Whether the menu opens. When false the child is shown as is.
final
enableHapticFeedback → bool
Whether a long press that opens the menu gives haptic feedback (iOS).
final
hashCode → int
The hash code for this object.
no setterinherited
items → List<CNPopupMenuEntry>
Entries of the menu: items, dividers and submenus.
final
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
onSelected → ValueChanged<List<int>>
Called with the path to the chosen item. Not called when the menu is closed without a choice.
final
previewCornerRadius → double
The corner radius of the lifted preview's platter, when showsPreview is on. Match the child's own corners, e.g. 12 for a card.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
showsPreview → bool
iOS: whether a long press lifts a preview of child, as a system context menu does in Photos or Messages: the child rises above the blurred screen with the menu beside it, and settles back when the menu closes (#138). Off, the menu opens at the pressed point with nothing lifted. macOS menus have no preview.
final

Methods

createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<CNContextMenu>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
liquidGlass({CNGlassEffect effect = CNGlassEffect.regular, CNGlassEffectShape shape = CNGlassEffectShape.capsule, double? cornerRadius, Color? tint, bool interactive = false}) → Widget

Available on Widget, provided by the LiquidGlassExtension extension

Applies a Liquid Glass effect to this widget.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited