582 lines
22 KiB
Dart
582 lines
22 KiB
Dart
// 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/foundation.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
/// Interactive states that some of the Material widgets can take on when
|
|
/// receiving input from the user.
|
|
///
|
|
/// States are defined by https://material.io/design/interaction/states.html#usage.
|
|
///
|
|
/// Some Material widgets track their current state in a `Set<MaterialState>`.
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [MaterialStateProperty], an interface for objects that "resolve" to
|
|
/// different values depending on a widget's material state.
|
|
/// * [MaterialStateColor], a [Color] that implements `MaterialStateProperty`
|
|
/// which is used in APIs that need to accept either a [Color] or a
|
|
/// `MaterialStateProperty<Color>`.
|
|
/// * [MaterialStateMouseCursor], a [MouseCursor] that implements
|
|
/// `MaterialStateProperty` which is used in APIs that need to accept either
|
|
/// a [MouseCursor] or a [MaterialStateProperty<MouseCursor>].
|
|
/// * [MaterialStateOutlinedBorder], an [OutlinedBorder] that implements
|
|
/// `MaterialStateProperty` which is used in APIs that need to accept either
|
|
/// an [OutlinedBorder] or a [MaterialStateProperty<OutlinedBorder>].
|
|
/// * [MaterialStateBorderSide], a [BorderSide] that implements
|
|
/// `MaterialStateProperty` which is used in APIs that need to accept either
|
|
/// a [BorderSide] or a [MaterialStateProperty<BorderSide>].
|
|
|
|
enum MaterialState {
|
|
/// The state when the user drags their mouse cursor over the given widget.
|
|
///
|
|
/// See: https://material.io/design/interaction/states.html#hover.
|
|
hovered,
|
|
|
|
/// The state when the user navigates with the keyboard to a given widget.
|
|
///
|
|
/// This can also sometimes be triggered when a widget is tapped. For example,
|
|
/// when a [TextField] is tapped, it becomes [focused].
|
|
///
|
|
/// See: https://material.io/design/interaction/states.html#focus.
|
|
focused,
|
|
|
|
/// The state when the user is actively pressing down on the given widget.
|
|
///
|
|
/// See: https://material.io/design/interaction/states.html#pressed.
|
|
pressed,
|
|
|
|
/// The state when this widget is being dragged from one place to another by
|
|
/// the user.
|
|
///
|
|
/// https://material.io/design/interaction/states.html#dragged.
|
|
dragged,
|
|
|
|
/// The state when this item has been selected.
|
|
///
|
|
/// This applies to things that can be toggled (such as chips and checkboxes)
|
|
/// and things that are selected from a set of options (such as tabs and radio buttons).
|
|
///
|
|
/// See: https://material.io/design/interaction/states.html#selected.
|
|
selected,
|
|
|
|
/// The state when this widget overlaps the content of a scrollable below.
|
|
///
|
|
/// Used by [AppBar] to indicate that the primary scrollable's
|
|
/// content has scrolled up and behind the app bar.
|
|
scrolledUnder,
|
|
|
|
/// The state when this widget is disabled and cannot be interacted with.
|
|
///
|
|
/// Disabled widgets should not respond to hover, focus, press, or drag
|
|
/// interactions.
|
|
///
|
|
/// See: https://material.io/design/interaction/states.html#disabled.
|
|
disabled,
|
|
|
|
/// The state when the widget has entered some form of invalid state.
|
|
///
|
|
/// See https://material.io/design/interaction/states.html#usage.
|
|
error,
|
|
}
|
|
|
|
/// Signature for the function that returns a value of type `T` based on a given
|
|
/// set of states.
|
|
typedef MaterialPropertyResolver<T> = T Function(Set<MaterialState> states);
|
|
|
|
/// Defines a [Color] that is also a [MaterialStateProperty].
|
|
///
|
|
/// This class exists to enable widgets with [Color] valued properties
|
|
/// to also accept [MaterialStateProperty<Color>] values. A material
|
|
/// state color property represents a color which depends on
|
|
/// a widget's "interactive state". This state is represented as a
|
|
/// [Set] of [MaterialState]s, like [MaterialState.pressed],
|
|
/// [MaterialState.focused] and [MaterialState.hovered].
|
|
///
|
|
/// To use a [MaterialStateColor], you can either:
|
|
/// 1. Create a subclass of [MaterialStateColor] and implement the abstract `resolve` method.
|
|
/// 2. Use [MaterialStateColor.resolveWith] and pass in a callback that
|
|
/// will be used to resolve the color in the given states.
|
|
///
|
|
/// If a [MaterialStateColor] is used for a property or a parameter that doesn't
|
|
/// support resolving [MaterialStateProperty<Color>]s, then its default color
|
|
/// value will be used for all states.
|
|
///
|
|
/// To define a `const` [MaterialStateColor], you'll need to extend
|
|
/// [MaterialStateColor] and override its [resolve] method. You'll also need
|
|
/// to provide a `defaultValue` to the super constructor, so that we can know
|
|
/// at compile-time what its default color is.
|
|
///
|
|
/// This class enables existing widget implementations with [Color]
|
|
/// properties to be extended to also effectively support `MaterialStateProperty<Color>`
|
|
/// property values. [MaterialStateColor] should only be used with widgets that document
|
|
/// their support, like [TimePickerThemeData.dayPeriodColor].
|
|
///
|
|
/// {@tool snippet}
|
|
///
|
|
/// This example defines a `MaterialStateColor` with a const constructor.
|
|
///
|
|
/// ```dart
|
|
/// class MyColor extends MaterialStateColor {
|
|
/// const MyColor() : super(_defaultColor);
|
|
///
|
|
/// static const int _defaultColor = 0xcafefeed;
|
|
/// static const int _pressedColor = 0xdeadbeef;
|
|
///
|
|
/// @override
|
|
/// Color resolve(Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.pressed)) {
|
|
/// return const Color(_pressedColor);
|
|
/// }
|
|
/// return const Color(_defaultColor);
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
/// {@end-tool}
|
|
abstract class MaterialStateColor extends Color implements MaterialStateProperty<Color> {
|
|
/// Abstract const constructor. This constructor enables subclasses to provide
|
|
/// const constructors so that they can be used in const expressions.
|
|
const MaterialStateColor(int defaultValue) : super(defaultValue);
|
|
|
|
/// Creates a [MaterialStateColor] from a [MaterialPropertyResolver<Color>]
|
|
/// callback function.
|
|
///
|
|
/// If used as a regular color, the color resolved in the default state (the
|
|
/// empty set of states) will be used.
|
|
///
|
|
/// The given callback parameter must return a non-null color in the default
|
|
/// state.
|
|
static MaterialStateColor resolveWith(MaterialPropertyResolver<Color> callback) => _MaterialStateColor(callback);
|
|
|
|
/// Returns a [Color] that's to be used when a Material component is in the
|
|
/// specified state.
|
|
@override
|
|
Color resolve(Set<MaterialState> states);
|
|
}
|
|
|
|
/// A [MaterialStateColor] created from a [MaterialPropertyResolver<Color>]
|
|
/// callback alone.
|
|
///
|
|
/// If used as a regular color, the color resolved in the default state will
|
|
/// be used.
|
|
///
|
|
/// Used by [MaterialStateColor.resolveWith].
|
|
class _MaterialStateColor extends MaterialStateColor {
|
|
_MaterialStateColor(this._resolve) : super(_resolve(_defaultStates).value);
|
|
|
|
final MaterialPropertyResolver<Color> _resolve;
|
|
|
|
/// The default state for a Material component, the empty set of interaction states.
|
|
static const Set<MaterialState> _defaultStates = <MaterialState>{};
|
|
|
|
@override
|
|
Color resolve(Set<MaterialState> states) => _resolve(states);
|
|
}
|
|
|
|
/// Defines a [MouseCursor] whose value depends on a set of [MaterialState]s which
|
|
/// represent the interactive state of a component.
|
|
///
|
|
/// This kind of [MouseCursor] is useful when the set of interactive
|
|
/// actions a widget supports varies with its state. For example, a
|
|
/// mouse pointer hovering over a disabled [ListTile] should not
|
|
/// display [SystemMouseCursors.click], since a disabled list tile
|
|
/// doesn't respond to mouse clicks. [ListTile]'s default mouse cursor
|
|
/// is a [MaterialStateMouseCursor.clickable], which resolves to
|
|
/// [SystemMouseCursors.basic] when the button is disabled.
|
|
///
|
|
/// To use a [MaterialStateMouseCursor], you should create a subclass of
|
|
/// [MaterialStateMouseCursor] and implement the abstract `resolve` method.
|
|
///
|
|
/// {@tool dartpad --template=stateless_widget_scaffold_center}
|
|
///
|
|
/// This example defines a mouse cursor that resolves to
|
|
/// [SystemMouseCursors.forbidden] when its widget is disabled.
|
|
///
|
|
/// ```dart imports
|
|
/// import 'package:flutter/rendering.dart';
|
|
/// ```
|
|
///
|
|
/// ```dart preamble
|
|
/// class ListTileCursor extends MaterialStateMouseCursor {
|
|
/// @override
|
|
/// MouseCursor resolve(Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.disabled)) {
|
|
/// return SystemMouseCursors.forbidden;
|
|
/// }
|
|
/// return SystemMouseCursors.click;
|
|
/// }
|
|
/// @override
|
|
/// String get debugDescription => 'ListTileCursor()';
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// ```dart
|
|
/// Widget build(BuildContext context) {
|
|
/// return ListTile(
|
|
/// title: const Text('Disabled ListTile'),
|
|
/// enabled: false,
|
|
/// mouseCursor: ListTileCursor(),
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
/// {@end-tool}
|
|
///
|
|
/// This class should only be used for parameters which are documented to take
|
|
/// [MaterialStateMouseCursor], otherwise only the default state will be used.
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [MouseCursor] for introduction on the mouse cursor system.
|
|
/// * [SystemMouseCursors], which defines cursors that are supported by
|
|
/// native platforms.
|
|
abstract class MaterialStateMouseCursor extends MouseCursor implements MaterialStateProperty<MouseCursor> {
|
|
/// Abstract const constructor. This constructor enables subclasses to provide
|
|
/// const constructors so that they can be used in const expressions.
|
|
const MaterialStateMouseCursor();
|
|
|
|
@protected
|
|
@override
|
|
MouseCursorSession createSession(int device) {
|
|
return resolve(<MaterialState>{}).createSession(device);
|
|
}
|
|
|
|
/// Returns a [MouseCursor] that's to be used when a Material component is in
|
|
/// the specified state.
|
|
///
|
|
/// This method should never return null.
|
|
@override
|
|
MouseCursor resolve(Set<MaterialState> states);
|
|
|
|
/// A mouse cursor for clickable material widgets, which resolves differently
|
|
/// when the widget is disabled.
|
|
///
|
|
/// By default this cursor resolves to [SystemMouseCursors.click]. If the widget is
|
|
/// disabled, the cursor resolves to [SystemMouseCursors.basic].
|
|
///
|
|
/// This cursor is the default for many Material widgets.
|
|
static const MaterialStateMouseCursor clickable = _EnabledAndDisabledMouseCursor(
|
|
enabledCursor: SystemMouseCursors.click,
|
|
disabledCursor: SystemMouseCursors.basic,
|
|
name: 'clickable',
|
|
);
|
|
|
|
/// A mouse cursor for material widgets related to text, which resolves differently
|
|
/// when the widget is disabled.
|
|
///
|
|
/// By default this cursor resolves to [SystemMouseCursors.text]. If the widget is
|
|
/// disabled, the cursor resolves to [SystemMouseCursors.basic].
|
|
///
|
|
/// This cursor is the default for many Material widgets.
|
|
static const MaterialStateMouseCursor textable = _EnabledAndDisabledMouseCursor(
|
|
enabledCursor: SystemMouseCursors.text,
|
|
disabledCursor: SystemMouseCursors.basic,
|
|
name: 'textable',
|
|
);
|
|
}
|
|
|
|
class _EnabledAndDisabledMouseCursor extends MaterialStateMouseCursor {
|
|
const _EnabledAndDisabledMouseCursor({
|
|
required this.enabledCursor,
|
|
required this.disabledCursor,
|
|
required this.name,
|
|
});
|
|
|
|
final MouseCursor enabledCursor;
|
|
final MouseCursor disabledCursor;
|
|
final String name;
|
|
|
|
@override
|
|
MouseCursor resolve(Set<MaterialState> states) {
|
|
if (states.contains(MaterialState.disabled)) {
|
|
return disabledCursor;
|
|
}
|
|
return enabledCursor;
|
|
}
|
|
|
|
@override
|
|
String get debugDescription => 'MaterialStateMouseCursor($name)';
|
|
}
|
|
|
|
/// Defines a [BorderSide] whose value depends on a set of [MaterialState]s
|
|
/// which represent the interactive state of a component.
|
|
///
|
|
/// To use a [MaterialStateBorderSide], you should create a subclass of a
|
|
/// [MaterialStateBorderSide] and override the abstract `resolve` method.
|
|
///
|
|
/// This class enables existing widget implementations with [BorderSide]
|
|
/// properties to be extended to also effectively support `MaterialStateProperty<BorderSide>`
|
|
/// property values. [MaterialStateBorderSide] should only be used with widgets that document
|
|
/// their support, like [ActionChip.side].
|
|
///
|
|
/// {@tool dartpad --template=stateful_widget_material}
|
|
///
|
|
/// This example defines a subclass of [MaterialStateBorderSide], that resolves
|
|
/// to a red border side when its widget is selected.
|
|
///
|
|
/// ```dart
|
|
/// bool isSelected = true;
|
|
///
|
|
/// @override
|
|
/// Widget build(BuildContext context) {
|
|
/// return FilterChip(
|
|
/// label: const Text('Select chip'),
|
|
/// selected: isSelected,
|
|
/// onSelected: (bool value) {
|
|
/// setState(() {
|
|
/// isSelected = value;
|
|
/// });
|
|
/// },
|
|
/// side: MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.selected)) {
|
|
/// return const BorderSide(width: 1, color: Colors.red);
|
|
/// }
|
|
/// return null; // Defer to default value on the theme or widget.
|
|
/// }),
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
/// {@end-tool}
|
|
///
|
|
/// This class should only be used for parameters which are documented to take
|
|
/// [MaterialStateBorderSide], otherwise only the default state will be used.
|
|
abstract class MaterialStateBorderSide extends BorderSide implements MaterialStateProperty<BorderSide?> {
|
|
/// Abstract const constructor. This constructor enables subclasses to provide
|
|
/// const constructors so that they can be used in const expressions.
|
|
const MaterialStateBorderSide();
|
|
|
|
/// Returns a [BorderSide] that's to be used when a Material component is
|
|
/// in the specified state. Return null to defer to the default value of the
|
|
/// widget or theme.
|
|
@override
|
|
BorderSide? resolve(Set<MaterialState> states);
|
|
|
|
/// Creates a [MaterialStateBorderSide] from a
|
|
/// [MaterialPropertyResolver<BorderSide?>] callback function.
|
|
///
|
|
/// If used as a regular [BorderSide], the border resolved in the default state
|
|
/// (the empty set of states) will be used.
|
|
///
|
|
/// Usage:
|
|
/// ```dart
|
|
/// ChipTheme(
|
|
/// data: Theme.of(context).chipTheme.copyWith(
|
|
/// side: MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.selected)) {
|
|
/// return const BorderSide(width: 1, color: Colors.red);
|
|
/// }
|
|
/// return null; // Defer to default value on the theme or widget.
|
|
/// }),
|
|
/// ),
|
|
/// child: Chip(),
|
|
/// )
|
|
///
|
|
/// // OR
|
|
///
|
|
/// Chip(
|
|
/// ...
|
|
/// side: MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.selected)) {
|
|
/// return const BorderSide(width: 1, color: Colors.red);
|
|
/// }
|
|
/// return null; // Defer to default value on the theme or widget.
|
|
/// }),
|
|
/// )
|
|
/// ```
|
|
static MaterialStateBorderSide resolveWith(MaterialPropertyResolver<BorderSide?> callback) =>
|
|
_MaterialStateBorderSide(callback);
|
|
}
|
|
|
|
/// A [MaterialStateBorderSide] created from a
|
|
/// [MaterialPropertyResolver<BorderSide>] callback alone.
|
|
///
|
|
/// If used as a regular side, the side resolved in the default state will
|
|
/// be used.
|
|
///
|
|
/// Used by [MaterialStateBorderSide.resolveWith].
|
|
class _MaterialStateBorderSide extends MaterialStateBorderSide {
|
|
const _MaterialStateBorderSide(this._resolve);
|
|
|
|
final MaterialPropertyResolver<BorderSide?> _resolve;
|
|
|
|
@override
|
|
BorderSide? resolve(Set<MaterialState> states) {
|
|
return _resolve(states);
|
|
}
|
|
}
|
|
|
|
/// Defines an [OutlinedBorder] whose value depends on a set of [MaterialState]s
|
|
/// which represent the interactive state of a component.
|
|
///
|
|
/// To use a [MaterialStateOutlinedBorder], you should create a subclass of an
|
|
/// [OutlinedBorder] and implement [MaterialStateOutlinedBorder]'s abstract
|
|
/// `resolve` method.
|
|
///
|
|
/// {@tool dartpad --template=stateful_widget_material}
|
|
///
|
|
/// This example defines a subclass of [RoundedRectangleBorder] and an
|
|
/// implementation of [MaterialStateOutlinedBorder], that resolves to
|
|
/// [RoundedRectangleBorder] when its widget is selected.
|
|
///
|
|
/// ```dart preamble
|
|
/// class SelectedBorder extends RoundedRectangleBorder implements MaterialStateOutlinedBorder {
|
|
/// @override
|
|
/// OutlinedBorder? resolve(Set<MaterialState> states) {
|
|
/// if (states.contains(MaterialState.selected)) {
|
|
/// return const RoundedRectangleBorder();
|
|
/// }
|
|
/// return null; // Defer to default value on the theme or widget.
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// ```dart
|
|
/// bool isSelected = true;
|
|
///
|
|
/// @override
|
|
/// Widget build(BuildContext context) {
|
|
/// return FilterChip(
|
|
/// label: const Text('Select chip'),
|
|
/// selected: isSelected,
|
|
/// onSelected: (bool value) {
|
|
/// setState(() {
|
|
/// isSelected = value;
|
|
/// });
|
|
/// },
|
|
/// shape: SelectedBorder(),
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
/// {@end-tool}
|
|
///
|
|
/// This class should only be used for parameters which are documented to take
|
|
/// [MaterialStateOutlinedBorder], otherwise only the default state will be used.
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [ShapeBorder] the base class for shape outlines.
|
|
abstract class MaterialStateOutlinedBorder extends OutlinedBorder implements MaterialStateProperty<OutlinedBorder?> {
|
|
/// Abstract const constructor. This constructor enables subclasses to provide
|
|
/// const constructors so that they can be used in const expressions.
|
|
const MaterialStateOutlinedBorder();
|
|
|
|
/// Returns an [OutlinedBorder] that's to be used when a Material component is
|
|
/// in the specified state. Return null to defer to the default value of the
|
|
/// widget or theme.
|
|
@override
|
|
OutlinedBorder? resolve(Set<MaterialState> states);
|
|
}
|
|
|
|
/// Interface for classes that [resolve] to a value of type `T` based
|
|
/// on a widget's interactive "state", which is defined as a set
|
|
/// of [MaterialState]s.
|
|
///
|
|
/// Material state properties represent values that depend on a widget's material
|
|
/// "state". The state is encoded as a set of [MaterialState] values, like
|
|
/// [MaterialState.focused], [MaterialState.hovered], [MaterialState.pressed]. For
|
|
/// example the [InkWell.overlayColor] defines the color that fills the ink well
|
|
/// when it's pressed (the "splash color"), focused, or hovered. The [InkWell]
|
|
/// uses the overlay color's [resolve] method to compute the color for the
|
|
/// ink well's current state.
|
|
///
|
|
/// [ButtonStyle], which is used to configure the appearance of
|
|
/// buttons like [TextButton], [ElevatedButton], and [OutlinedButton],
|
|
/// has many material state properties. The button widgets keep track
|
|
/// of their current material state and [resolve] the button style's
|
|
/// material state properties when their value is needed.
|
|
///
|
|
/// {@tool dartpad --template=stateless_widget_scaffold_center}
|
|
///
|
|
/// This example shows how you can override the default text and icon
|
|
/// color (the "foreground color") of a [TextButton] with a
|
|
/// [MaterialStateProperty]. In this example, the button's text color
|
|
/// will be `Colors.blue` when the button is being pressed, hovered,
|
|
/// or focused. Otherwise, the text color will be `Colors.red`.
|
|
///
|
|
/// ```dart
|
|
/// Widget build(BuildContext context) {
|
|
/// Color getColor(Set<MaterialState> states) {
|
|
/// const Set<MaterialState> interactiveStates = <MaterialState>{
|
|
/// MaterialState.pressed,
|
|
/// MaterialState.hovered,
|
|
/// MaterialState.focused,
|
|
/// };
|
|
/// if (states.any(interactiveStates.contains)) {
|
|
/// return Colors.blue;
|
|
/// }
|
|
/// return Colors.red;
|
|
/// }
|
|
/// return TextButton(
|
|
/// style: ButtonStyle(
|
|
/// foregroundColor: MaterialStateProperty.resolveWith(getColor),
|
|
/// ),
|
|
/// onPressed: () {},
|
|
/// child: const Text('TextButton'),
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
/// {@end-tool}
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [MaterialStateColor], a [Color] that implements `MaterialStateProperty`
|
|
/// which is used in APIs that need to accept either a [Color] or a
|
|
/// `MaterialStateProperty<Color>`.
|
|
/// * [MaterialStateMouseCursor], a [MouseCursor] that implements `MaterialStateProperty`
|
|
/// which is used in APIs that need to accept either a [MouseCursor] or a
|
|
/// [MaterialStateProperty<MouseCursor>].
|
|
abstract class MaterialStateProperty<T> {
|
|
|
|
/// Returns a value of type `T` that depends on [states].
|
|
///
|
|
/// Widgets like [TextButton] and [ElevatedButton] apply this method to their
|
|
/// current [MaterialState]s to compute colors and other visual parameters
|
|
/// at build time.
|
|
T resolve(Set<MaterialState> states);
|
|
|
|
/// Resolves the value for the given set of states if `value` is a
|
|
/// [MaterialStateProperty], otherwise returns the value itself.
|
|
///
|
|
/// This is useful for widgets that have parameters which can optionally be a
|
|
/// [MaterialStateProperty]. For example, [InkWell.mouseCursor] can be a
|
|
/// [MouseCursor] or a [MaterialStateProperty<MouseCursor>].
|
|
static T resolveAs<T>(T value, Set<MaterialState> states) {
|
|
if (value is MaterialStateProperty<T>) {
|
|
final MaterialStateProperty<T> property = value;
|
|
return property.resolve(states);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/// Convenience method for creating a [MaterialStateProperty] from a
|
|
/// [MaterialPropertyResolver] function alone.
|
|
static MaterialStateProperty<T> resolveWith<T>(MaterialPropertyResolver<T> callback) => _MaterialStatePropertyWith<T>(callback);
|
|
|
|
/// Convenience method for creating a [MaterialStateProperty] that resolves
|
|
/// to a single value for all states.
|
|
static MaterialStateProperty<T> all<T>(T value) => _MaterialStatePropertyAll<T>(value);
|
|
}
|
|
|
|
class _MaterialStatePropertyWith<T> implements MaterialStateProperty<T> {
|
|
_MaterialStatePropertyWith(this._resolve);
|
|
|
|
final MaterialPropertyResolver<T> _resolve;
|
|
|
|
@override
|
|
T resolve(Set<MaterialState> states) => _resolve(states);
|
|
}
|
|
|
|
class _MaterialStatePropertyAll<T> implements MaterialStateProperty<T> {
|
|
_MaterialStatePropertyAll(this.value);
|
|
|
|
final T value;
|
|
|
|
@override
|
|
T resolve(Set<MaterialState> states) => value;
|
|
|
|
@override
|
|
String toString() => 'MaterialStateProperty.all($value)';
|
|
}
|