Unverified Commit 2eb26f13 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Update AnimatedDefaultTextStyle to match DefaultTextStyle (#13531)

We've added a bunch of non-animatable properties to DefaultTextStyle.
This adds them to AnimatedDefaultTextStyle so that you can use them
even when your text style is animating.
parent ee65db11
...@@ -945,18 +945,29 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> { ...@@ -945,18 +945,29 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> {
/// default text style (the text style to apply to descendant [Text] widgets /// default text style (the text style to apply to descendant [Text] widgets
/// without explicit style) over a given duration whenever the given style /// without explicit style) over a given duration whenever the given style
/// changes. /// changes.
///
/// The [textAlign], [softWrap], [textOverflow], and [maxLines] properties are
/// not animated and take effect immediately when changed.
class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget { class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
/// Creates a widget that animates the default text style implicitly. /// Creates a widget that animates the default text style implicitly.
/// ///
/// The [child], [style], [curve], and [duration] arguments must not be null. /// The [child], [style], [softWrap], [overflow], [curve], and [duration]
/// arguments must not be null.
const AnimatedDefaultTextStyle({ const AnimatedDefaultTextStyle({
Key key, Key key,
@required this.child, @required this.child,
@required this.style, @required this.style,
this.textAlign,
this.softWrap: true,
this.overflow: TextOverflow.clip,
this.maxLines,
Curve curve: Curves.linear, Curve curve: Curves.linear,
@required Duration duration, @required Duration duration,
}) : assert(style != null), }) : assert(style != null),
assert(child != null), assert(child != null),
assert(softWrap != null),
assert(overflow != null),
assert(maxLines == null || maxLines > 0),
super(key: key, curve: curve, duration: duration); super(key: key, curve: curve, duration: duration);
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
...@@ -965,8 +976,34 @@ class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget { ...@@ -965,8 +976,34 @@ class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
/// The target text style. /// The target text style.
/// ///
/// The text style must not be null. /// The text style must not be null.
///
/// When this property is changed, the style will be animated over [duration] time.
final TextStyle style; final TextStyle style;
/// How the text should be aligned horizontally.
///
/// This property takes effect immediately when changed, it is not animated.
final TextAlign textAlign;
/// Whether the text should break at soft line breaks.
///
/// This property takes effect immediately when changed, it is not animated.
///
/// See [DefaultTextStyle.softWrap] for more details.
final bool softWrap;
/// How visual overflow should be handled.
///
/// This property takes effect immediately when changed, it is not animated.
final TextOverflow overflow;
/// An optional maximum number of lines for the text to span, wrapping if necessary.
///
/// This property takes effect immediately when changed, it is not animated.
///
/// See [DefaultTextStyle.maxLines] for more details.
final int maxLines;
@override @override
_AnimatedDefaultTextStyleState createState() => new _AnimatedDefaultTextStyleState(); _AnimatedDefaultTextStyleState createState() => new _AnimatedDefaultTextStyleState();
...@@ -974,6 +1011,10 @@ class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget { ...@@ -974,6 +1011,10 @@ class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
void debugFillProperties(DiagnosticPropertiesBuilder description) { void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description); super.debugFillProperties(description);
style?.debugFillProperties(description); style?.debugFillProperties(description);
description.add(new EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
description.add(new FlagProperty('softWrap', value: softWrap, ifTrue: 'wrapping at box width', ifFalse: 'no wrapping except at line break characters', showName: true));
description.add(new EnumProperty<TextOverflow>('overflow', overflow, defaultValue: null));
description.add(new IntProperty('maxLines', maxLines, defaultValue: null));
} }
} }
...@@ -989,7 +1030,11 @@ class _AnimatedDefaultTextStyleState extends AnimatedWidgetBaseState<AnimatedDef ...@@ -989,7 +1030,11 @@ class _AnimatedDefaultTextStyleState extends AnimatedWidgetBaseState<AnimatedDef
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new DefaultTextStyle( return new DefaultTextStyle(
style: _style.evaluate(animation), style: _style.evaluate(animation),
child: widget.child textAlign: widget.textAlign,
softWrap: widget.softWrap,
overflow: widget.overflow,
maxLines: widget.maxLines,
child: widget.child,
); );
} }
} }
......
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
softWrap: false, softWrap: false,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
maxLines: 3, maxLines: 3,
child: textWidget child: textWidget,
)); ));
text = tester.firstWidget(find.byType(RichText)); text = tester.firstWidget(find.byType(RichText));
...@@ -40,4 +40,60 @@ void main() { ...@@ -40,4 +40,60 @@ void main() {
expect(text.overflow, TextOverflow.fade); expect(text.overflow, TextOverflow.fade);
expect(text.maxLines, 3); expect(text.maxLines, 3);
}); });
testWidgets('AnimatedDefaultTextStyle changes propagate to Text', (WidgetTester tester) async {
const Text textWidget = const Text('Hello', textDirection: TextDirection.ltr);
const TextStyle s1 = const TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w800,
height: 123.0,
);
const TextStyle s2 = const TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w200,
height: 1.0,
);
await tester.pumpWidget(const AnimatedDefaultTextStyle(
style: s1,
child: textWidget,
duration: const Duration(milliseconds: 1000),
));
final RichText text1 = tester.firstWidget(find.byType(RichText));
expect(text1, isNotNull);
expect(text1.text.style, s1);
expect(text1.textAlign, TextAlign.start);
expect(text1.softWrap, isTrue);
expect(text1.overflow, TextOverflow.clip);
expect(text1.maxLines, isNull);
await tester.pumpWidget(const AnimatedDefaultTextStyle(
style: s2,
textAlign: TextAlign.justify,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 3,
child: textWidget,
duration: const Duration(milliseconds: 1000),
));
final RichText text2 = tester.firstWidget(find.byType(RichText));
expect(text2, isNotNull);
expect(text2.text.style, s1); // animation hasn't started yet
expect(text2.textAlign, TextAlign.justify);
expect(text2.softWrap, false);
expect(text2.overflow, TextOverflow.fade);
expect(text2.maxLines, 3);
await tester.pump(const Duration(milliseconds: 1000));
final RichText text3 = tester.firstWidget(find.byType(RichText));
expect(text3, isNotNull);
expect(text3.text.style, s2); // animation has now finished
expect(text3.textAlign, TextAlign.justify);
expect(text3.softWrap, false);
expect(text3.overflow, TextOverflow.fade);
expect(text3.maxLines, 3);
});
} }
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