Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions examples/api/lib/material/dropdown_menu/dropdown_menu.1.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

/// Flutter code sample for [DropdownMenu].

const List<String> list = <String>['One', 'Two', 'Three', 'Four'];

void main() => runApp(const DropdownMenuApp());

class DropdownMenuApp extends StatelessWidget {
const DropdownMenuApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3:true),
home: Scaffold(
appBar: AppBar(title: const Text('DropdownMenu Sample')),
body: const Center(
child: DropdownMenuExample(),
),
),
);
}
}

class DropdownMenuExample extends StatefulWidget {
const DropdownMenuExample({super.key});

@override
State<DropdownMenuExample> createState() => _DropdownMenuExampleState();
}

class _DropdownMenuExampleState extends State<DropdownMenuExample> {
String dropdownValue = list.first;

@override
Widget build(BuildContext context) {
return DropdownMenu<String>(
initialSelection: list.first,
onSelected: (String? value) {
// This is called when the user selects an item.
setState(() {
dropdownValue = value!;
});
},
dropdownMenuEntries: list.map<DropdownMenuEntry<String>>((String value) {
return DropdownMenuEntry<String>(
value: value,
label: value
);
}).toList(),
);
}
}
66 changes: 66 additions & 0 deletions examples/api/lib/material/menu_anchor/menu_anchor.2.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

/// Flutter code sample for [MenuAnchor].

// This is the type used by the menu below.
enum SampleItem { itemOne, itemTwo, itemThree }

void main() => runApp(const MenuAnchorApp());

class MenuAnchorApp extends StatelessWidget {
const MenuAnchorApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const MenuAnchorExample(),
);
}
}

class MenuAnchorExample extends StatefulWidget {
const MenuAnchorExample({super.key});

@override
State<MenuAnchorExample> createState() => _MenuAnchorExampleState();
}

class _MenuAnchorExampleState extends State<MenuAnchorExample> {
SampleItem? selectedMenu;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('MenuAnchorButton')),
body: Center(
child: MenuAnchor(
builder:
(BuildContext context, MenuController controller, Widget? child) {
return IconButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
icon: const Icon(Icons.more_horiz),
tooltip: 'Show menu',
);},
menuChildren: List<MenuItemButton>.generate(
3,
(int index) => MenuItemButton(
onPressed: () => setState(() => selectedMenu = SampleItem.values[index]),
child: Text('Item ${index + 1}'),
),
),
),
),
);
}
}
47 changes: 45 additions & 2 deletions packages/flutter/lib/src/material/dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,44 @@ class DropdownButtonHideUnderline extends InheritedWidget {
/// shows the currently selected item as well as an arrow that opens a menu for
/// selecting another item.
///
/// ## Updating to [DropdownMenu]
///
/// There is a Material 3 version of this component,
/// [DropdownMenu] that is preferred for applications that are configured
/// for Material 3 (see [ThemeData.useMaterial3]).
/// The [DropdownMenu] widget's visuals
/// are a little bit different, see the Material 3 spec at
/// <https://m3.material.io/components/menus/guidelines> for
/// more details.
///
/// The [DropdownMenu] widget's API is also slightly different.
/// To update from [DropdownButton] to [DropdownMenu], you will
/// need to make the following changes:
///
/// 1. Instead of using [DropdownButton.items], which
/// takes a list of [DropdownMenuItem]s, use
/// [DropdownMenu.dropdownMenuEntries], which
/// takes a list of [DropdownMenuEntry]'s.
///
/// 2. Instead of using [DropdownButton.onChanged],
/// use [DropdownMenu.onSelected], which is also
/// a callback that is called when the user selects an entry.
///
/// 3. In [DropdownMenu] it is not required to track
/// the current selection in your app's state.
/// So, instead of tracking the current selection in
/// the [DropdownButton.value] property, you can set the
/// [DropdownMenu.initialSelection] property to the
/// item that should be selected before there is any user action.
///
/// 4. You may also need to make changes to the styling of the
/// [DropdownMenu], see the properties in the [DropdownMenu]
/// constructor for more details.
///
/// See the sample below for an example of migrating
/// from [DropdownButton] to [DropdownMenu].
///
/// ## Using [DropdownButton]
/// {@youtube 560 315 https://www.youtube.com/watch?v=ZzQ_PWrFihg}
///
/// One ancestor must be a [Material] widget and typically this is
Expand All @@ -802,6 +840,7 @@ class DropdownButtonHideUnderline extends InheritedWidget {
/// dropdown's value. It should also call [State.setState] to rebuild the
/// dropdown with the new value.
///
///
/// {@tool dartpad}
/// This sample shows a [DropdownButton] with a large arrow icon,
/// purple text style, and bold purple underline, whose value is one of "One",
Expand All @@ -819,9 +858,13 @@ class DropdownButtonHideUnderline extends InheritedWidget {
/// [disabledHint] is null and [hint] is non-null, the [hint] widget will
/// instead be displayed.
///
/// Requires one of its ancestors to be a [Material] widget.
/// {@tool dartpad}
/// This sample shows how you would rewrite the above [DropdownButton]
/// to use the [DropdownMenu].
///
/// ** See code in examples/api/lib/material/dropdown_menu/dropdown_menu.1.dart **
/// {@end-tool}
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=ZzQ_PWrFihg}
///
/// See also:
///
Expand Down
41 changes: 41 additions & 0 deletions packages/flutter/lib/src/material/popup_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,41 @@ typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext
/// If both are null, then a standard overflow icon is created (depending on the
/// platform).
///
/// /// ## Updating to [MenuAnchor]
///
/// There is a Material 3 component,
/// [MenuAnchor] that is preferred for applications that are configured
/// for Material 3 (see [ThemeData.useMaterial3]).
/// The [MenuAnchor] widget's visuals
/// are a little bit different, see the Material 3 spec at
/// <https://m3.material.io/components/menus/guidelines> for
/// more details.
///
/// The [MenuAnchor] widget's API is also slightly different.
/// [MenuAnchor]'s were built to be lower level interface for
/// creating menus that are displayed from an anchor.
///
/// There are a few steps you would take to migrate from
/// [PopupMenuButton] to [MenuAnchor]:
///
/// 1. Instead of using the [PopupMenuButton.itemBuilder] to build
/// a list of [PopupMenuEntry]s, you would use the [MenuAnchor.menuChildren]
/// which takes a list of [Widget]s. Usually, you would use a list of
/// [MenuItemButton]s as shown in the example below.
///
/// 2. Instead of using the [PopupMenuButton.onSelected] callback, you would
/// set individual callbacks for each of the [MenuItemButton]s using the
/// [MenuItemButton.onPressed] property.
///
/// 3. To anchor the [MenuAnchor] to a widget, you would use the [MenuAnchor.builder]
/// to return the widget of choice - usually a [TextButton] or an [IconButton].
///
/// 4. You may want to style the [MenuItemButton]s, see the [MenuItemButton]
/// documentation for details.
///
/// Use the sample below for an example of migrating from [PopupMenuButton] to
/// [MenuAnchor].
///
/// {@tool dartpad}
/// This example shows a menu with three items, selecting between an enum's
/// values and setting a `selectedMenu` field based on the selection.
Expand All @@ -1022,6 +1057,12 @@ typedef PopupMenuItemBuilder<T> = List<PopupMenuEntry<T>> Function(BuildContext
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows how to migrate the above to a [MenuAnchor].
///
/// ** See code in examples/api/lib/material/menu_anchor/menu_anchor.2.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This sample shows the creation of a popup menu, as described in:
/// https://m3.material.io/components/menus/overview
///
Expand Down