Commit a5a34d97 authored by Ian Hickson's avatar Ian Hickson

AnimatedDefaultTextStyle (#3324)

parent c40f4cfe
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'ink_well.dart'; import 'ink_well.dart';
import 'material.dart'; import 'material.dart';
...@@ -190,8 +191,9 @@ abstract class MaterialButtonState<T extends MaterialButton> extends State<T> { ...@@ -190,8 +191,9 @@ abstract class MaterialButtonState<T extends MaterialButton> extends State<T> {
child: contents child: contents
); );
} else { } else {
contents = new DefaultTextStyle( contents = new AnimatedDefaultTextStyle(
style: style, style: style,
duration: kThemeChangeDuration,
child: contents child: contents
); );
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'icon.dart'; import 'icon.dart';
import 'icons.dart'; import 'icons.dart';
...@@ -102,8 +103,9 @@ class DrawerItem extends StatelessWidget { ...@@ -102,8 +103,9 @@ class DrawerItem extends StatelessWidget {
new Flexible( new Flexible(
child: new Padding( child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new DefaultTextStyle( child: new AnimatedDefaultTextStyle(
style: _getTextStyle(themeData), style: _getTextStyle(themeData),
duration: kThemeChangeDuration,
child: child child: child
) )
) )
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'ink_well.dart'; import 'ink_well.dart';
import 'theme.dart'; import 'theme.dart';
...@@ -166,8 +167,9 @@ class ListItem extends StatelessWidget { ...@@ -166,8 +167,9 @@ class ListItem extends StatelessWidget {
)); ));
} }
final Widget primaryLine = new DefaultTextStyle( final Widget primaryLine = new AnimatedDefaultTextStyle(
style: _primaryTextStyle(context), style: _primaryTextStyle(context),
duration: kThemeChangeDuration,
child: title ?? new Container() child: title ?? new Container()
); );
Widget center = primaryLine; Widget center = primaryLine;
...@@ -177,8 +179,9 @@ class ListItem extends StatelessWidget { ...@@ -177,8 +179,9 @@ class ListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
primaryLine, primaryLine,
new DefaultTextStyle( new AnimatedDefaultTextStyle(
style: _secondaryTextStyle(context), style: _secondaryTextStyle(context),
duration: kThemeChangeDuration,
child: subtitle child: subtitle
) )
] ]
......
...@@ -202,8 +202,9 @@ class _MaterialState extends State<Material> { ...@@ -202,8 +202,9 @@ class _MaterialState extends State<Material> {
Color backgroundColor = _getBackgroundColor(context); Color backgroundColor = _getBackgroundColor(context);
Widget contents = config.child; Widget contents = config.child;
if (contents != null) { if (contents != null) {
contents = new DefaultTextStyle( contents = new AnimatedDefaultTextStyle(
style: config.textStyle ?? Theme.of(context).textTheme.body1, style: config.textStyle ?? Theme.of(context).textTheme.body1,
duration: kThemeChangeDuration,
child: contents child: contents
); );
} }
......
...@@ -6,6 +6,7 @@ import 'dart:async'; ...@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'constants.dart';
import 'divider.dart'; import 'divider.dart';
import 'icon.dart'; import 'icon.dart';
import 'icons.dart'; import 'icons.dart';
...@@ -90,8 +91,9 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> { ...@@ -90,8 +91,9 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> {
if (!config.enabled) if (!config.enabled)
style = style.copyWith(color: theme.disabledColor); style = style.copyWith(color: theme.disabledColor);
Widget item = new DefaultTextStyle( Widget item = new AnimatedDefaultTextStyle(
style: style, style: style,
duration: kThemeChangeDuration,
child: new Baseline( child: new Baseline(
baseline: config.height - _kBaselineOffsetFromBottom, baseline: config.height - _kBaselineOffsetFromBottom,
child: buildChild() child: buildChild()
......
...@@ -851,9 +851,9 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -851,9 +851,9 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
indicatorColor = Colors.white; indicatorColor = Colors.white;
} }
TextStyle textStyle = themeData.primaryTextTheme.body2; final TextStyle textStyle = themeData.primaryTextTheme.body2;
IconThemeData iconTheme = themeData.primaryIconTheme; final IconThemeData iconTheme = themeData.primaryIconTheme;
Color textColor = themeData.primaryTextTheme.body2.color.withAlpha(0xB2); // 70% alpha final Color textColor = themeData.primaryTextTheme.body2.color.withAlpha(0xB2); // 70% alpha
List<Widget> tabs = <Widget>[]; List<Widget> tabs = <Widget>[];
bool textAndIcons = false; bool textAndIcons = false;
......
...@@ -48,6 +48,16 @@ class Matrix4Tween extends Tween<Matrix4> { ...@@ -48,6 +48,16 @@ class Matrix4Tween extends Tween<Matrix4> {
} }
} }
/// An interpolation between two [TextStyle]s.
///
/// This will not work well if the styles don't set the same fields.
class TextStyleTween extends Tween<TextStyle> {
TextStyleTween({ TextStyle begin, TextStyle end }) : super(begin: begin, end: end);
@override
TextStyle lerp(double t) => TextStyle.lerp(begin, end, t);
}
/// An abstract widget for building widgets that gradually change their /// An abstract widget for building widgets that gradually change their
/// values over a period of time. /// values over a period of time.
abstract class ImplicitlyAnimatedWidget extends StatefulWidget { abstract class ImplicitlyAnimatedWidget extends StatefulWidget {
...@@ -504,3 +514,55 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> { ...@@ -504,3 +514,55 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> {
); );
} }
} }
/// Animated version of [DefaultTextStyle] which automatically
/// transitions the default text style (the text style to apply to
/// descendant [Text] widgets without explicit style) over a given
/// duration whenever the given style changes.
class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
AnimatedDefaultTextStyle({
Key key,
this.child,
this.style,
Curve curve: Curves.linear,
Duration duration
}) : super(key: key, curve: curve, duration: duration) {
assert(style != null);
assert(child != null);
}
/// The widget below this widget in the tree.
final Widget child;
/// The target text style.
///
/// The text style must not be null.
final TextStyle style;
@override
_AnimatedDefaultTextStyleState createState() => new _AnimatedDefaultTextStyleState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
'$style'.split('\n').forEach(description.add);
}
}
class _AnimatedDefaultTextStyleState extends AnimatedWidgetBaseState<AnimatedDefaultTextStyle> {
TextStyleTween _style;
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
// TODO(ianh): Use constructor tear-offs when it becomes possible
_style = visitor(_style, config.style, (dynamic value) => new TextStyleTween(begin: value));
}
@override
Widget build(BuildContext context) {
return new DefaultTextStyle(
style: _style.evaluate(animation),
child: config.child
);
}
}
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