Commit 643ab478 authored by Matt Perry's avatar Matt Perry

CheckedPopupMenuItem now fades its icon when changed.

BUG=https://github.com/flutter/flutter/issues/2274
parent 96a0e7cb
...@@ -28,7 +28,7 @@ const double _kMenuVerticalPadding = 8.0; ...@@ -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> { ...@@ -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> { ...@@ -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,12 +94,15 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> { ...@@ -79,12 +94,15 @@ class PopupMenuItem<T> extends PopupMenuEntry<T> {
); );
} }
return new MergeSemantics( return new InkWell(
onTap: config.enabled ? onTap : null,
child: new MergeSemantics(
child: new Container( child: new Container(
height: height, height: config.height,
padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding), padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
child: item child: item
) )
)
); );
} }
} }
...@@ -93,19 +111,52 @@ class CheckedPopupMenuItem<T> extends PopupMenuItem<T> { ...@@ -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 { ...@@ -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 { ...@@ -137,10 +187,7 @@ class _PopupMenu<T> extends StatelessComponent {
} }
children.add(new FadeTransition( children.add(new FadeTransition(
opacity: opacity, opacity: opacity,
child: new InkWell(
onTap: enabled ? () { Navigator.pop(context, route.items[i].value); } : null,
child: item child: item
)
)); ));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment