ios_adaptive_context_menu 0.1.4
ios_adaptive_context_menu: ^0.1.4 copied to clipboard
Flutter plugin for adaptive single-tap context menus on iOS and Android.
ios_adaptive_context_menu #
Flutter plugin for showing adaptive single-tap context menus on iOS and Android.
Features #
- Opens the iOS system context menu with a single tap.
- Opens a Material popup context menu on Android with the same API.
- Supports actions, dividers, and nested submenus.
- Supports SF Symbols (
iconSystemName) and SVG asset icons (iconAssetPath). - Uses a unified action model across iOS and Android.
Requirements #
- Flutter
>=3.13.0 - iOS
14.0+
Installation #
dependencies:
ios_adaptive_context_menu: ^0.1.0
Run Example App #
cd example
flutter pub get
flutter run -d ios
Usage #
import 'package:flutter/material.dart';
import 'package:ios_adaptive_context_menu/ios_adaptive_context_menu.dart';
class DemoMenuButton extends StatelessWidget {
const DemoMenuButton({super.key});
@override
Widget build(BuildContext context) {
return IosSingleTapContextMenu(
actions: const [
IosContextMenuAction(
id: 'share',
title: 'Share',
iconSystemName: 'square.and.arrow.up',
),
IosContextMenuDivider(),
IosContextMenuAction(
id: 'delete',
title: 'Delete',
iconSystemName: 'trash',
destructive: true,
),
],
onSelected: (id) {
debugPrint('Selected action: $id');
},
child: const ListTile(
title: Text('Tap me'),
subtitle: Text('Shows iOS native context menu'),
),
);
}
}
API #
IosSingleTapContextMenuIosContextMenuActionIosContextMenuDividerIosContextMenuSubmenu
Why this approach is stable in Flutter UI #
When UIKit content is kept permanently embedded in the Flutter view hierarchy, it can cause rendering and interaction issues in some layouts.
This package avoids that by using an on-demand native bridge:
- The user taps a Flutter widget.
- The tap is forwarded to native iOS code.
- Native creates a temporary invisible UIKit anchor (
UIButton) only for menu presentation. - The system context menu is shown from that temporary anchor.
- The anchor is cleaned up after selection/dismissal (and also on widget dispose).
Because no persistent UIKit view is mounted inside Flutter for normal rendering, this approach prevents common Flutter UI breakage caused by long-lived UIKit embedding.
Screenshots #
| iOS | Android |
|---|---|
![]() |
![]() |


