CheckedPopupMenuItem now fades its icon when changed.
BUG=https://github.com/flutter/flutter/issues/2274
This commit is contained in:
parent
96a0e7cbb2
commit
643ab478ff
@ -28,7 +28,7 @@ const double _kMenuVerticalPadding = 8.0;
|
|||||||
const double _kMenuWidthStep = 56.0;
|
const double _kMenuWidthStep = 56.0;
|
||||||
const double _kMenuScreenPadding = 8.0;
|
const double _kMenuScreenPadding = 8.0;
|
||||||
|
|
||||||
abstract class PopupMenuEntry<T> extends StatelessComponent {
|
abstract class PopupMenuEntry<T> extends StatefulComponent {
|
||||||
PopupMenuEntry({ Key key }) : super(key: key);
|
PopupMenuEntry({ Key key }) : super(key: key);
|
||||||
|
|
||||||
double get height;
|
double get height;
|
||||||
@ -41,7 +41,11 @@ class PopupMenuDivider extends PopupMenuEntry<dynamic> {
|
|||||||
|
|
||||||
final double height;
|
final double height;
|
||||||
|
|
||||||
Widget build(BuildContext context) => new Divider(height: height);
|
_PopupMenuDividerState createState() => new _PopupMenuDividerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PopupMenuDividerState extends State<PopupMenuDivider> {
|
||||||
|
Widget build(BuildContext context) => new Divider(height: config.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PopupMenuItem<T> extends PopupMenuEntry<T> {
|
class PopupMenuItem<T> extends PopupMenuEntry<T> {
|
||||||
@ -58,20 +62,31 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
|
|||||||
|
|
||||||
double get height => _kMenuItemHeight;
|
double get height => _kMenuItemHeight;
|
||||||
|
|
||||||
|
_PopupMenuItemState<PopupMenuItem<T>> createState() => new _PopupMenuItemState<PopupMenuItem<T>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PopupMenuItemState<T extends PopupMenuItem> extends State<T> {
|
||||||
|
// Override this to put something else in the menu entry.
|
||||||
|
Widget buildChild() => config.child;
|
||||||
|
|
||||||
|
void onTap() {
|
||||||
|
Navigator.pop(context, config.value);
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
TextStyle style = theme.text.subhead;
|
TextStyle style = theme.text.subhead;
|
||||||
if (!enabled)
|
if (!config.enabled)
|
||||||
style = style.copyWith(color: theme.disabledColor);
|
style = style.copyWith(color: theme.disabledColor);
|
||||||
|
|
||||||
Widget item = new DefaultTextStyle(
|
Widget item = new DefaultTextStyle(
|
||||||
style: style,
|
style: style,
|
||||||
child: new Baseline(
|
child: new Baseline(
|
||||||
baseline: height - _kBaselineOffsetFromBottom,
|
baseline: config.height - _kBaselineOffsetFromBottom,
|
||||||
child: child
|
child: buildChild()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (!enabled) {
|
if (!config.enabled) {
|
||||||
final bool isDark = theme.brightness == ThemeBrightness.dark;
|
final bool isDark = theme.brightness == ThemeBrightness.dark;
|
||||||
item = new IconTheme(
|
item = new IconTheme(
|
||||||
data: new IconThemeData(opacity: isDark ? 0.5 : 0.38),
|
data: new IconThemeData(opacity: isDark ? 0.5 : 0.38),
|
||||||
@ -79,11 +94,14 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MergeSemantics(
|
return new InkWell(
|
||||||
child: new Container(
|
onTap: config.enabled ? onTap : null,
|
||||||
height: height,
|
child: new MergeSemantics(
|
||||||
padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
|
child: new Container(
|
||||||
child: item
|
height: config.height,
|
||||||
|
padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
|
||||||
|
child: item
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -93,19 +111,52 @@ class CheckedPopupMenuItem<T> extends PopupMenuItem<T> {
|
|||||||
CheckedPopupMenuItem({
|
CheckedPopupMenuItem({
|
||||||
Key key,
|
Key key,
|
||||||
T value,
|
T value,
|
||||||
checked: false,
|
this.checked: false,
|
||||||
bool enabled: true,
|
bool enabled: true,
|
||||||
Widget child
|
Widget child
|
||||||
}) : super(
|
}) : super(
|
||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
child: new ListItem(
|
child: child
|
||||||
enabled: enabled,
|
|
||||||
left: new Icon(icon: checked ? Icons.done : null),
|
|
||||||
primary: child
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final bool checked;
|
||||||
|
|
||||||
|
_CheckedPopupMenuItemState<T> createState() => new _CheckedPopupMenuItemState<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CheckedPopupMenuItemState<T> extends _PopupMenuItemState<CheckedPopupMenuItem<T>> {
|
||||||
|
static const Duration _kFadeDuration = const Duration(milliseconds: 150);
|
||||||
|
AnimationController _controller;
|
||||||
|
Animation<double> get _opacity => _controller.view;
|
||||||
|
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = new AnimationController(duration: _kFadeDuration)
|
||||||
|
..value = config.checked ? 1.0 : 0.0
|
||||||
|
..addListener(() => setState(() { /* animation changed */ }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTap() {
|
||||||
|
// This fades the checkmark in or out when tapped.
|
||||||
|
if (config.checked)
|
||||||
|
_controller.reverse();
|
||||||
|
else
|
||||||
|
_controller.forward();
|
||||||
|
super.onTap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildChild() {
|
||||||
|
return new ListItem(
|
||||||
|
enabled: config.enabled,
|
||||||
|
left: new FadeTransition(
|
||||||
|
opacity: _opacity,
|
||||||
|
child: new Icon(icon: _controller.isDismissed ? null : Icons.done)
|
||||||
|
),
|
||||||
|
primary: config.child
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PopupMenu<T> extends StatelessComponent {
|
class _PopupMenu<T> extends StatelessComponent {
|
||||||
@ -127,7 +178,6 @@ class _PopupMenu<T> extends StatelessComponent {
|
|||||||
parent: route.animation,
|
parent: route.animation,
|
||||||
curve: new Interval(start, end)
|
curve: new Interval(start, end)
|
||||||
);
|
);
|
||||||
final bool enabled = route.items[i].enabled;
|
|
||||||
Widget item = route.items[i];
|
Widget item = route.items[i];
|
||||||
if (route.initialValue != null && route.initialValue == route.items[i].value) {
|
if (route.initialValue != null && route.initialValue == route.items[i].value) {
|
||||||
item = new Container(
|
item = new Container(
|
||||||
@ -137,10 +187,7 @@ class _PopupMenu<T> extends StatelessComponent {
|
|||||||
}
|
}
|
||||||
children.add(new FadeTransition(
|
children.add(new FadeTransition(
|
||||||
opacity: opacity,
|
opacity: opacity,
|
||||||
child: new InkWell(
|
child: item
|
||||||
onTap: enabled ? () { Navigator.pop(context, route.items[i].value); } : null,
|
|
||||||
child: item
|
|
||||||
)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user