mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Disable context menu (#128365)
## Description Changes the context menu example for `MenuAnchor` so that it uses right-click, or (on macOS and iOS only) ctrl-left-click, for the context menu. Also disables the browser context menu on web platforms. ## Tests - Updated test to reflect new triggers.
This commit is contained in:
parent
5328bd9ae0
commit
36f73cf645
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@ -41,6 +42,7 @@ class _MyContextMenuState extends State<MyContextMenu> {
|
||||
final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Menu Button');
|
||||
final MenuController _menuController = MenuController();
|
||||
ShortcutRegistryEntry? _shortcutsEntry;
|
||||
bool _menuWasEnabled = false;
|
||||
|
||||
Color get backgroundColor => _backgroundColor;
|
||||
Color _backgroundColor = Colors.red;
|
||||
@ -62,6 +64,12 @@ class _MyContextMenuState extends State<MyContextMenu> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_disableContextMenu();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
@ -84,15 +92,38 @@ class _MyContextMenuState extends State<MyContextMenu> {
|
||||
void dispose() {
|
||||
_shortcutsEntry?.dispose();
|
||||
_buttonFocusNode.dispose();
|
||||
_reenableContextMenu();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _disableContextMenu() async {
|
||||
if (!kIsWeb) {
|
||||
// Does nothing on non-web platforms.
|
||||
return;
|
||||
}
|
||||
_menuWasEnabled = BrowserContextMenu.enabled;
|
||||
if (_menuWasEnabled) {
|
||||
await BrowserContextMenu.disableContextMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void _reenableContextMenu() {
|
||||
if (!kIsWeb) {
|
||||
// Does nothing on non-web platforms.
|
||||
return;
|
||||
}
|
||||
if (_menuWasEnabled && !BrowserContextMenu.enabled) {
|
||||
BrowserContextMenu.enableContextMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(50),
|
||||
child: GestureDetector(
|
||||
onTapDown: _handleTapDown,
|
||||
onSecondaryTapDown: _handleSecondaryTapDown,
|
||||
child: MenuAnchor(
|
||||
controller: _menuController,
|
||||
anchorTapClosesMenu: true,
|
||||
@ -142,7 +173,7 @@ class _MyContextMenuState extends State<MyContextMenu> {
|
||||
children: <Widget>[
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Text('Ctrl-click anywhere on the background to show the menu.'),
|
||||
child: Text('Right-click anywhere on the background to show the menu.'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
@ -185,13 +216,29 @@ class _MyContextMenuState extends State<MyContextMenu> {
|
||||
}
|
||||
}
|
||||
|
||||
void _handleTapDown(TapDownDetails details) {
|
||||
if (!HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlLeft) &&
|
||||
!HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlRight)) {
|
||||
return;
|
||||
}
|
||||
void _handleSecondaryTapDown(TapDownDetails details) {
|
||||
_menuController.open(position: details.localPosition);
|
||||
}
|
||||
|
||||
void _handleTapDown(TapDownDetails details) {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.linux:
|
||||
case TargetPlatform.windows:
|
||||
// Don't open the menu on these platforms with a Ctrl-tap (or a
|
||||
// tap).
|
||||
break;
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
// Only open the menu on these platforms if the control button is down
|
||||
// when the tap occurs.
|
||||
if (HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlLeft) ||
|
||||
HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlRight)) {
|
||||
_menuController.open(position: details.localPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ContextMenuApp extends StatelessWidget {
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_api_samples/material/menu_anchor/menu_anchor.1.dart' as example;
|
||||
@ -18,15 +19,13 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(const example.ContextMenuApp());
|
||||
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight);
|
||||
await tester.tapAt(const Offset(100, 200));
|
||||
await tester.tapAt(const Offset(100, 200), buttons: kSecondaryButton);
|
||||
await tester.pump();
|
||||
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(100.0, 200.0, 433.0, 360.0)));
|
||||
|
||||
// Make sure tapping in a different place causes the menu to move.
|
||||
await tester.tapAt(const Offset(200, 100));
|
||||
await tester.tapAt(const Offset(200, 100), buttons: kSecondaryButton);
|
||||
await tester.pump();
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlRight);
|
||||
|
||||
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(200.0, 100.0, 533.0, 260.0)));
|
||||
|
||||
@ -67,8 +66,7 @@ void main() {
|
||||
);
|
||||
|
||||
// Open the menu so we can look for state changes reflected in the menu.
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight);
|
||||
await tester.tapAt(const Offset(100, 200));
|
||||
await tester.tapAt(const Offset(100, 200), buttons: kSecondaryButton);
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text(example.MenuEntry.showMessage.label), findsOneWidget);
|
||||
|
Loading…
Reference in New Issue
Block a user