Skip to content

Commit eadda3c

Browse files
authored
Add Material 3 Popup Menu example and update existing example (#114228)
1 parent 8fe8728 commit eadda3c

File tree

7 files changed

+209
-114
lines changed

7 files changed

+209
-114
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
/// Flutter code sample for [PopupMenuButton].
6+
7+
import 'package:flutter/material.dart';
8+
9+
// This is the type used by the popup menu below.
10+
enum SampleItem { itemOne, itemTwo, itemThree }
11+
12+
void main() => runApp(const PopupMenuApp());
13+
14+
class PopupMenuApp extends StatelessWidget {
15+
const PopupMenuApp({super.key});
16+
17+
@override
18+
Widget build(BuildContext context) {
19+
return const MaterialApp(
20+
home: PopupMenuExample(),
21+
);
22+
}
23+
}
24+
25+
class PopupMenuExample extends StatefulWidget {
26+
const PopupMenuExample({super.key});
27+
28+
@override
29+
State<PopupMenuExample> createState() => _PopupMenuExampleState();
30+
}
31+
32+
class _PopupMenuExampleState extends State<PopupMenuExample> {
33+
SampleItem? selectedMenu;
34+
35+
@override
36+
Widget build(BuildContext context) {
37+
return Scaffold(
38+
appBar: AppBar(title: const Text('PopupMenuButton')),
39+
body: Center(
40+
child: PopupMenuButton<SampleItem>(
41+
initialValue: selectedMenu,
42+
// Callback that sets the selected popup menu item.
43+
onSelected: (SampleItem item) {
44+
setState(() {
45+
selectedMenu = item;
46+
});
47+
},
48+
itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[
49+
const PopupMenuItem<SampleItem>(
50+
value: SampleItem.itemOne,
51+
child: Text('Item 1'),
52+
),
53+
const PopupMenuItem<SampleItem>(
54+
value: SampleItem.itemTwo,
55+
child: Text('Item 2'),
56+
),
57+
const PopupMenuItem<SampleItem>(
58+
value: SampleItem.itemThree,
59+
child: Text('Item 3'),
60+
),
61+
],
62+
),
63+
),
64+
);
65+
}
66+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
/// Flutter code sample for [PopupMenuButton].
6+
7+
import 'package:flutter/material.dart';
8+
9+
// This is the type used by the popup menu below.
10+
enum SampleItem { itemOne, itemTwo, itemThree }
11+
12+
void main() => runApp(const PopupMenuApp());
13+
14+
class PopupMenuApp extends StatelessWidget {
15+
const PopupMenuApp({super.key});
16+
17+
@override
18+
Widget build(BuildContext context) {
19+
return MaterialApp(
20+
theme: ThemeData(useMaterial3: true, colorSchemeSeed: const Color(0xff6750a4)),
21+
home: const PopupMenuExample(),
22+
);
23+
}
24+
}
25+
26+
class PopupMenuExample extends StatefulWidget {
27+
const PopupMenuExample({super.key});
28+
29+
@override
30+
State<PopupMenuExample> createState() => _PopupMenuExampleState();
31+
}
32+
33+
class _PopupMenuExampleState extends State<PopupMenuExample> {
34+
SampleItem? selectedMenu;
35+
36+
@override
37+
Widget build(BuildContext context) {
38+
return Scaffold(
39+
appBar: AppBar(title: const Text('PopupMenuButton')),
40+
body: Center(
41+
child: PopupMenuButton<SampleItem>(
42+
initialValue: selectedMenu,
43+
// Callback that sets the selected popup menu item.
44+
onSelected: (SampleItem item) {
45+
setState(() {
46+
selectedMenu = item;
47+
});
48+
},
49+
itemBuilder: (BuildContext context) => <PopupMenuEntry<SampleItem>>[
50+
const PopupMenuItem<SampleItem>(
51+
value: SampleItem.itemOne,
52+
child: Text('Item 1'),
53+
),
54+
const PopupMenuItem<SampleItem>(
55+
value: SampleItem.itemTwo,
56+
child: Text('Item 2'),
57+
),
58+
const PopupMenuItem<SampleItem>(
59+
value: SampleItem.itemThree,
60+
child: Text('Item 3'),
61+
),
62+
],
63+
),
64+
),
65+
);
66+
}
67+
}

examples/api/lib/material/popupmenu/popupmenu.0.dart

Lines changed: 0 additions & 77 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter_api_samples/material/popup_menu/popup_menu.0.dart' as example;
7+
import 'package:flutter_test/flutter_test.dart';
8+
9+
void main() {
10+
testWidgets('Can open popup menu', (WidgetTester tester) async {
11+
const String menuItem = 'Item 1';
12+
13+
await tester.pumpWidget(
14+
const MaterialApp(
15+
home: Scaffold(
16+
body: example.PopupMenuApp(),
17+
),
18+
),
19+
);
20+
21+
expect(find.text(menuItem), findsNothing);
22+
23+
// Open popup menu.
24+
await tester.tap(find.byIcon(Icons.adaptive.more));
25+
await tester.pumpAndSettle();
26+
expect(find.text(menuItem), findsOneWidget);
27+
28+
// Close popup menu.
29+
await tester.tapAt(const Offset(1, 1));
30+
await tester.pumpAndSettle();
31+
expect(find.text(menuItem), findsNothing);
32+
});
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter_api_samples/material/popup_menu/popup_menu.1.dart' as example;
7+
import 'package:flutter_test/flutter_test.dart';
8+
9+
void main() {
10+
testWidgets('Can open popup menu', (WidgetTester tester) async {
11+
const String menuItem = 'Item 1';
12+
13+
await tester.pumpWidget(
14+
const MaterialApp(
15+
home: Scaffold(
16+
body: example.PopupMenuApp(),
17+
),
18+
),
19+
);
20+
21+
expect(find.text(menuItem), findsNothing);
22+
23+
// Open popup menu.
24+
await tester.tap(find.byIcon(Icons.adaptive.more));
25+
await tester.pumpAndSettle();
26+
expect(find.text(menuItem), findsOneWidget);
27+
28+
// Close popup menu.
29+
await tester.tapAt(const Offset(1, 1));
30+
await tester.pumpAndSettle();
31+
expect(find.text(menuItem), findsNothing);
32+
});
33+
}

examples/api/test/material/popupmenu/popupmenu.0_test.dart

Lines changed: 0 additions & 34 deletions
This file was deleted.

packages/flutter/lib/src/material/popup_menu.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,10 +1017,17 @@ typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext
10171017
/// platform).
10181018
///
10191019
/// {@tool dartpad}
1020-
/// This example shows a menu with four items, selecting between an enum's
1021-
/// values and setting a `_selectedMenu` field based on the selection
1020+
/// This example shows a menu with three items, selecting between an enum's
1021+
/// values and setting a `selectedMenu` field based on the selection.
10221022
///
1023-
/// ** See code in examples/api/lib/material/popupmenu/popupmenu.0.dart **
1023+
/// ** See code in examples/api/lib/material/popup_menu/popup_menu.0.dart **
1024+
/// {@end-tool}
1025+
///
1026+
/// {@tool dartpad}
1027+
/// This sample shows the creation of a popup menu, as described in:
1028+
/// https://m3.material.io/components/menus/overview
1029+
///
1030+
/// ** See code in examples/api/lib/material/popup_menu/popup_menu.1.dart **
10241031
/// {@end-tool}
10251032
///
10261033
/// See also:

0 commit comments

Comments
 (0)