CheckedPopupMenuItem now fades its icon when changed.

BUG=https://github.com/flutter/flutter/issues/2274
diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart
index 2effaf7..c6701d4 100644
--- a/packages/flutter/lib/src/material/popup_menu.dart
+++ b/packages/flutter/lib/src/material/popup_menu.dart
@@ -28,7 +28,7 @@
 const double _kMenuWidthStep = 56.0;
 const double _kMenuScreenPadding = 8.0;
 
-abstract class PopupMenuEntry<T> extends StatelessComponent {
+abstract class PopupMenuEntry<T> extends StatefulComponent {
   PopupMenuEntry({ Key key }) : super(key: key);
 
   double get height;
@@ -41,7 +41,11 @@
 
   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> {
@@ -58,20 +62,31 @@
 
   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) {
     final ThemeData theme = Theme.of(context);
     TextStyle style = theme.text.subhead;
-    if (!enabled)
+    if (!config.enabled)
       style = style.copyWith(color: theme.disabledColor);
 
     Widget item = new DefaultTextStyle(
       style: style,
       child: new Baseline(
-        baseline: height - _kBaselineOffsetFromBottom,
-        child: child
+        baseline: config.height - _kBaselineOffsetFromBottom,
+        child: buildChild()
       )
     );
-    if (!enabled) {
+    if (!config.enabled) {
       final bool isDark = theme.brightness == ThemeBrightness.dark;
       item = new IconTheme(
         data: new IconThemeData(opacity: isDark ? 0.5 : 0.38),
@@ -79,11 +94,14 @@
       );
     }
 
-    return new MergeSemantics(
-      child: new Container(
-        height: height,
-        padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
-        child: item
+    return new InkWell(
+      onTap: config.enabled ? onTap : null,
+      child: new MergeSemantics(
+        child: new Container(
+          height: config.height,
+          padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
+          child: item
+        )
       )
     );
   }
@@ -93,19 +111,52 @@
   CheckedPopupMenuItem({
     Key key,
     T value,
-    checked: false,
+    this.checked: false,
     bool enabled: true,
     Widget child
   }) : super(
     key: key,
     value: value,
     enabled: enabled,
-    child: new ListItem(
-      enabled: enabled,
-      left: new Icon(icon: checked ? Icons.done : null),
-      primary: child
-    )
+    child: 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 {
@@ -127,7 +178,6 @@
         parent: route.animation,
         curve: new Interval(start, end)
       );
-      final bool enabled = route.items[i].enabled;
       Widget item = route.items[i];
       if (route.initialValue != null && route.initialValue == route.items[i].value) {
         item = new Container(
@@ -137,10 +187,7 @@
       }
       children.add(new FadeTransition(
         opacity: opacity,
-        child: new InkWell(
-          onTap: enabled ? () { Navigator.pop(context, route.items[i].value); } : null,
-          child: item
-        )
+        child: item
       ));
     }