Another context menus example: custom menu (#1577)

pull/1585/head
Justin McCandless 3 years ago committed by GitHub
parent 56c01c31be
commit 6bd2d930bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,6 +27,10 @@ Shows how to create a context menu with cascading submenus using
### [Custom buttons](https://github.com/flutter/samples/blob/main/experimental/context_menus/lib/custom_buttons_page.dart)
Shows how to customize the default buttons in the existing context menus.
### [Custom menu](https://github.com/flutter/samples/blob/main/experimental/context_menus/lib/custom_menu_page.dart)
Shows how to use any custom widgets as the menu itself, including the option to
keep the default buttons.
### [Default values](https://github.com/flutter/samples/blob/main/experimental/context_menus/lib/default_values_page.dart)
Demonstrates how the
[contextMenuBuilder](https://master-api.flutter.dev/flutter/material/TextField/contextMenuBuilder.html)

@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'constants.dart';
import 'platform_selector.dart';
class CustomMenuPage extends StatelessWidget {
CustomMenuPage({
Key? key,
required this.onChangedPlatform,
}) : super(key: key);
static const String route = 'custom-menu';
static const String title = 'Custom Menu';
static const String subtitle =
'A custom menu built from scratch, but using the default buttons.';
final PlatformCallback onChangedPlatform;
final TextEditingController _controller = TextEditingController(
text: 'Show the menu to see a custom menu with the default buttons.',
);
static const String url = '$kCodeUrl/custom_menu_page.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(CustomMenuPage.title),
actions: <Widget>[
PlatformSelector(
onChangedPlatform: onChangedPlatform,
),
IconButton(
icon: const Icon(Icons.code),
onPressed: () async {
if (!await launchUrl(Uri.parse(url))) {
throw 'Could not launch $url';
}
},
),
],
),
body: Center(
child: SizedBox(
width: 300.0,
child: TextField(
controller: _controller,
maxLines: 4,
minLines: 2,
contextMenuBuilder:
(BuildContext context, EditableTextState editableTextState) {
return _MyContextMenu(
anchor: editableTextState.contextMenuAnchors.primaryAnchor,
children: AdaptiveTextSelectionToolbar.getAdaptiveButtons(
context,
editableTextState.contextMenuButtonItems,
).toList(),
);
},
),
),
),
);
}
}
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: Container(
width: 200.0,
height: 200.0,
color: Colors.amberAccent,
child: Column(
children: children,
),
),
),
],
);
}
}

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'anywhere_page.dart';
import 'cascading_menu_page.dart';
import 'custom_buttons_page.dart';
import 'custom_menu_page.dart';
import 'default_values_page.dart';
import 'email_button_page.dart';
import 'field_types_page.dart';
@ -51,6 +52,8 @@ class _MyAppState extends State<MyApp> {
AnywherePage(onChangedPlatform: onChangedPlatform),
CustomButtonsPage.route: (context) =>
CustomButtonsPage(onChangedPlatform: onChangedPlatform),
CustomMenuPage.route: (context) =>
CustomMenuPage(onChangedPlatform: onChangedPlatform),
ReorderedButtonsPage.route: (context) =>
ReorderedButtonsPage(onChangedPlatform: onChangedPlatform),
EmailButtonPage.route: (context) =>
@ -115,6 +118,11 @@ class MyHomePage extends StatelessWidget {
title: CustomButtonsPage.title,
subtitle: CustomButtonsPage.subtitle,
),
_MyListItem(
route: CustomMenuPage.route,
title: CustomMenuPage.title,
subtitle: CustomMenuPage.subtitle,
),
_MyListItem(
route: EmailButtonPage.route,
title: EmailButtonPage.title,

@ -14,7 +14,7 @@ void main() {
await tester.dragUntilVisible(
find.text(CascadingMenuPage.title),
find.byType(ListView),
const Offset(0.0, -300.0),
const Offset(0.0, -250.0),
);
await tester.tap(find.text(CascadingMenuPage.title));
await tester.pumpAndSettle();

@ -0,0 +1,58 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:context_menus/main.dart';
import 'package:context_menus/custom_menu_page.dart';
void main() {
testWidgets('Shows default buttons in a custom context menu',
(WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
// Navigate to the CustomMenuPage example.
await tester.dragUntilVisible(
find.text(CustomMenuPage.title),
find.byType(ListView),
const Offset(0.0, -200.0),
);
await tester.tap(find.text(CustomMenuPage.title));
await tester.pumpAndSettle();
// Right click on the text field to show the context menu.
final TestGesture gesture = await tester.startGesture(
tester.getCenter(find.byType(EditableText)),
kind: PointerDeviceKind.mouse,
buttons: kSecondaryMouseButton,
);
await tester.pump();
await gesture.up();
await gesture.removePointer();
await tester.pumpAndSettle();
// A custom context menu is shown, and the buttons are the default ones.
expect(find.byType(AdaptiveTextSelectionToolbar), findsNothing);
expect(find.byType(CupertinoAdaptiveTextSelectionToolbar), findsNothing);
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
expect(
find.byType(CupertinoTextSelectionToolbarButton), findsNWidgets(2));
break;
case TargetPlatform.macOS:
expect(find.byType(CupertinoDesktopTextSelectionToolbarButton),
findsNWidgets(2));
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
expect(find.byType(TextSelectionToolbarTextButton), findsNWidgets(1));
break;
case TargetPlatform.linux:
case TargetPlatform.windows:
expect(
find.byType(DesktopTextSelectionToolbarButton), findsNWidgets(1));
break;
}
});
}
Loading…
Cancel
Save