123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import 'package:flutter/material.dart';
- class PopupMenuItem<T> extends PopupMenuEntry<T> {
- /// Creates an item for a popup menu.
- ///
- /// By default, the item is [enabled].
- ///
- /// The `enabled` and `height` arguments must not be null.
- const PopupMenuItem({
- Key key,
- this.value,
- this.enabled = true,
- this.height = kMinInteractiveDimension,
- this.textStyle,
- @required this.child,
- }) : assert(enabled != null),
- assert(height != null),
- super(key: key);
- /// The value that will be returned by [showMenu] if this entry is selected.
- final T value;
- /// Whether the user is permitted to select this item.
- ///
- /// Defaults to true. If this is false, then the item will not react to
- /// touches.
- final bool enabled;
- /// The minimum height height of the menu item.
- ///
- /// Defaults to [kMinInteractiveDimension] pixels.
- @override
- final double height;
- /// The text style of the popup menu item.
- ///
- /// If this property is null, then [PopupMenuThemeData.textStyle] is used.
- /// If [PopupMenuThemeData.textStyle] is also null, then [ThemeData.textTheme.subtitle1] is used.
- final TextStyle textStyle;
- /// The widget below this widget in the tree.
- ///
- /// Typically a single-line [ListTile] (for menus with icons) or a [Text]. An
- /// appropriate [DefaultTextStyle] is put in scope for the child. In either
- /// case, the text should be short enough that it won't wrap.
- final Widget child;
- @override
- bool represents(T value) => value == this.value;
- @override
- PopupMenuItemState<T, PopupMenuItem<T>> createState() => PopupMenuItemState<T, PopupMenuItem<T>>();
- }
- /// The [State] for [PopupMenuItem] subclasses.
- ///
- /// By default this implements the basic styling and layout of Material Design
- /// popup menu items.
- ///
- /// The [buildChild] method can be overridden to adjust exactly what gets placed
- /// in the menu. By default it returns [PopupMenuItem.child].
- ///
- /// The [handleTap] method can be overridden to adjust exactly what happens when
- /// the item is tapped. By default, it uses [Navigator.pop] to return the
- /// [PopupMenuItem.value] from the menu route.
- ///
- /// This class takes two type arguments. The second, `W`, is the exact type of
- /// the [Widget] that is using this [State]. It must be a subclass of
- /// [PopupMenuItem]. The first, `T`, must match the type argument of that widget
- /// class, and is the type of values returned from this menu.
- class PopupMenuItemState<T, W extends PopupMenuItem<T>> extends State<W> {
- /// The menu item contents.
- ///
- /// Used by the [build] method.
- ///
- /// By default, this returns [PopupMenuItem.child]. Override this to put
- /// something else in the menu entry.
- @protected
- Widget buildChild() => widget.child;
- /// The handler for when the user selects the menu item.
- ///
- /// Used by the [InkWell] inserted by the [build] method.
- ///
- /// By default, uses [Navigator.pop] to return the [PopupMenuItem.value] from
- /// the menu route.
- @protected
- void handleTap() {
- Navigator.pop<T>(context, widget.value);
- }
- @override
- Widget build(BuildContext context) {
- final ThemeData theme = Theme.of(context);
- final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
- TextStyle style = widget.textStyle ?? popupMenuTheme.textStyle ?? theme.textTheme.subtitle1;
- if (!widget.enabled)
- style = style.copyWith(color: theme.disabledColor);
- Widget item = AnimatedDefaultTextStyle(
- style: style,
- duration: kThemeChangeDuration,
- child: Container(
- alignment: AlignmentDirectional.centerStart,
- constraints: BoxConstraints(minHeight: widget.height),
- padding: const EdgeInsets.symmetric(horizontal: 8.0),
- child: buildChild(),
- ),
- );
- if (!widget.enabled) {
- final bool isDark = theme.brightness == Brightness.dark;
- item = IconTheme.merge(
- data: IconThemeData(opacity: isDark ? 0.5 : 0.38),
- child: item,
- );
- }
- return InkWell(
- onTap: widget.enabled ? handleTap : null,
- canRequestFocus: widget.enabled,
- child: item,
- );
- }
- }
|