Commit 9fc9f402 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add RTL support for AnimatedCrossFade and AnimatedSize (#11920)

Fixes #11848
parent 9be9a409
...@@ -72,13 +72,14 @@ class RenderAnimatedSize extends RenderAligningShiftedBox { ...@@ -72,13 +72,14 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
@required TickerProvider vsync, @required TickerProvider vsync,
@required Duration duration, @required Duration duration,
Curve curve: Curves.linear, Curve curve: Curves.linear,
FractionalOffset alignment: FractionalOffset.center, FractionalOffsetGeometry alignment: FractionalOffset.center,
TextDirection textDirection,
RenderBox child, RenderBox child,
}) : assert(vsync != null), }) : assert(vsync != null),
assert(duration != null), assert(duration != null),
assert(curve != null), assert(curve != null),
_vsync = vsync, _vsync = vsync,
super(child: child, alignment: alignment) { super(child: child, alignment: alignment, textDirection: textDirection) {
_controller = new AnimationController( _controller = new AnimationController(
vsync: vsync, vsync: vsync,
duration: duration, duration: duration,
......
...@@ -166,7 +166,7 @@ class AnimatedCrossFade extends StatefulWidget { ...@@ -166,7 +166,7 @@ class AnimatedCrossFade extends StatefulWidget {
/// How the children should be aligned while the size is animating. /// How the children should be aligned while the size is animating.
/// ///
/// Defaults to [FractionalOffset.topCenter]. /// Defaults to [FractionalOffset.topCenter].
final FractionalOffset alignment; final FractionalOffsetGeometry alignment;
/// A builder that positions the [firstChild] and [secondChild] widgets. /// A builder that positions the [firstChild] and [secondChild] widgets.
/// ///
...@@ -218,7 +218,7 @@ class AnimatedCrossFade extends StatefulWidget { ...@@ -218,7 +218,7 @@ class AnimatedCrossFade extends StatefulWidget {
void debugFillProperties(DiagnosticPropertiesBuilder description) { void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description); super.debugFillProperties(description);
description.add(new EnumProperty<CrossFadeState>('crossFadeState', crossFadeState)); description.add(new EnumProperty<CrossFadeState>('crossFadeState', crossFadeState));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, defaultValue: FractionalOffset.topCenter)); description.add(new DiagnosticsProperty<FractionalOffsetGeometry>('alignment', alignment, defaultValue: FractionalOffset.topCenter));
} }
} }
...@@ -356,6 +356,6 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid ...@@ -356,6 +356,6 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
super.debugFillProperties(description); super.debugFillProperties(description);
description.add(new EnumProperty<CrossFadeState>('crossFadeState', widget.crossFadeState)); description.add(new EnumProperty<CrossFadeState>('crossFadeState', widget.crossFadeState));
description.add(new DiagnosticsProperty<AnimationController>('controller', _controller, showName: false)); description.add(new DiagnosticsProperty<AnimationController>('controller', _controller, showName: false));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', widget.alignment, defaultValue: FractionalOffset.topCenter)); description.add(new DiagnosticsProperty<FractionalOffsetGeometry>('alignment', widget.alignment, defaultValue: FractionalOffset.topCenter));
} }
} }
...@@ -34,7 +34,7 @@ class AnimatedSize extends SingleChildRenderObjectWidget { ...@@ -34,7 +34,7 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
/// edge of the parent. Other values interpolate (and extrapolate) linearly. /// edge of the parent. Other values interpolate (and extrapolate) linearly.
/// For example, a value of 0.5 means that the center of the child is aligned /// For example, a value of 0.5 means that the center of the child is aligned
/// with the center of the parent. /// with the center of the parent.
final FractionalOffset alignment; final FractionalOffsetGeometry alignment;
/// The animation curve when transitioning this widget's size to match the /// The animation curve when transitioning this widget's size to match the
/// child's size. /// child's size.
...@@ -54,16 +54,17 @@ class AnimatedSize extends SingleChildRenderObjectWidget { ...@@ -54,16 +54,17 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
duration: duration, duration: duration,
curve: curve, curve: curve,
vsync: vsync, vsync: vsync,
textDirection: Directionality.of(context),
); );
} }
@override @override
void updateRenderObject(BuildContext context, void updateRenderObject(BuildContext context, RenderAnimatedSize renderObject) {
RenderAnimatedSize renderObject) {
renderObject renderObject
..alignment = alignment ..alignment = alignment
..duration = duration ..duration = duration
..curve = curve ..curve = curve
..vsync = vsync; ..vsync = vsync
..textDirection = Directionality.of(context);
} }
} }
...@@ -14,16 +14,16 @@ void main() { ...@@ -14,16 +14,16 @@ void main() {
child: const AnimatedCrossFade( child: const AnimatedCrossFade(
firstChild: const SizedBox( firstChild: const SizedBox(
width: 100.0, width: 100.0,
height: 100.0 height: 100.0,
), ),
secondChild: const SizedBox( secondChild: const SizedBox(
width: 200.0, width: 200.0,
height: 200.0 height: 200.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showFirst, crossFadeState: CrossFadeState.showFirst,
) ),
) ),
); );
expect(find.byType(FadeTransition), findsNWidgets(2)); expect(find.byType(FadeTransition), findsNWidgets(2));
...@@ -36,16 +36,16 @@ void main() { ...@@ -36,16 +36,16 @@ void main() {
child: const AnimatedCrossFade( child: const AnimatedCrossFade(
firstChild: const SizedBox( firstChild: const SizedBox(
width: 100.0, width: 100.0,
height: 100.0 height: 100.0,
), ),
secondChild: const SizedBox( secondChild: const SizedBox(
width: 200.0, width: 200.0,
height: 200.0 height: 200.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showSecond, crossFadeState: CrossFadeState.showSecond,
) ),
) ),
); );
await tester.pump(const Duration(milliseconds: 100)); await tester.pump(const Duration(milliseconds: 100));
...@@ -62,16 +62,16 @@ void main() { ...@@ -62,16 +62,16 @@ void main() {
child: const AnimatedCrossFade( child: const AnimatedCrossFade(
firstChild: const SizedBox( firstChild: const SizedBox(
width: 100.0, width: 100.0,
height: 100.0 height: 100.0,
), ),
secondChild: const SizedBox( secondChild: const SizedBox(
width: 200.0, width: 200.0,
height: 200.0 height: 200.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showSecond, crossFadeState: CrossFadeState.showSecond,
) ),
) ),
); );
expect(find.byType(FadeTransition), findsNWidgets(2)); expect(find.byType(FadeTransition), findsNWidgets(2));
...@@ -80,7 +80,7 @@ void main() { ...@@ -80,7 +80,7 @@ void main() {
expect(box.size.height, equals(200.0)); expect(box.size.height, equals(200.0));
}); });
testWidgets('AnimatedCrossFade alignment', (WidgetTester tester) async { testWidgets('AnimatedCrossFade alignment (VISUAL)', (WidgetTester tester) async {
final Key firstKey = new UniqueKey(); final Key firstKey = new UniqueKey();
final Key secondKey = new UniqueKey(); final Key secondKey = new UniqueKey();
...@@ -91,17 +91,17 @@ void main() { ...@@ -91,17 +91,17 @@ void main() {
firstChild: new SizedBox( firstChild: new SizedBox(
key: firstKey, key: firstKey,
width: 100.0, width: 100.0,
height: 100.0 height: 100.0,
), ),
secondChild: new SizedBox( secondChild: new SizedBox(
key: secondKey, key: secondKey,
width: 200.0, width: 200.0,
height: 200.0 height: 200.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showFirst crossFadeState: CrossFadeState.showFirst,
) ),
) ),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -111,17 +111,75 @@ void main() { ...@@ -111,17 +111,75 @@ void main() {
firstChild: new SizedBox( firstChild: new SizedBox(
key: firstKey, key: firstKey,
width: 100.0, width: 100.0,
height: 100.0 height: 100.0,
), ),
secondChild: new SizedBox( secondChild: new SizedBox(
key: secondKey, key: secondKey,
width: 200.0, width: 200.0,
height: 200.0 height: 200.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showSecond crossFadeState: CrossFadeState.showSecond,
) ),
) ),
);
await tester.pump(const Duration(milliseconds: 100));
final RenderBox box1 = tester.renderObject(find.byKey(firstKey));
final RenderBox box2 = tester.renderObject(find.byKey(secondKey));
expect(box1.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
expect(box2.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
});
testWidgets('AnimatedCrossFade alignment (LTR)', (WidgetTester tester) async {
final Key firstKey = new UniqueKey();
final Key secondKey = new UniqueKey();
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Center(
child: new AnimatedCrossFade(
alignment: FractionalOffsetDirectional.bottomEnd,
firstChild: new SizedBox(
key: firstKey,
width: 100.0,
height: 100.0,
),
secondChild: new SizedBox(
key: secondKey,
width: 200.0,
height: 200.0,
),
duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showFirst,
),
),
),
);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Center(
child: new AnimatedCrossFade(
alignment: FractionalOffsetDirectional.bottomEnd,
firstChild: new SizedBox(
key: firstKey,
width: 100.0,
height: 100.0,
),
secondChild: new SizedBox(
key: secondKey,
width: 200.0,
height: 200.0,
),
duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showSecond,
),
),
),
); );
await tester.pump(const Duration(milliseconds: 100)); await tester.pump(const Duration(milliseconds: 100));
...@@ -132,6 +190,64 @@ void main() { ...@@ -132,6 +190,64 @@ void main() {
expect(box2.localToGlobal(Offset.zero), const Offset(275.0, 175.0)); expect(box2.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
}); });
testWidgets('AnimatedCrossFade alignment (RTL)', (WidgetTester tester) async {
final Key firstKey = new UniqueKey();
final Key secondKey = new UniqueKey();
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.rtl,
child: new Center(
child: new AnimatedCrossFade(
alignment: FractionalOffsetDirectional.bottomEnd,
firstChild: new SizedBox(
key: firstKey,
width: 100.0,
height: 100.0,
),
secondChild: new SizedBox(
key: secondKey,
width: 200.0,
height: 200.0,
),
duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showFirst,
),
),
),
);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.rtl,
child: new Center(
child: new AnimatedCrossFade(
alignment: FractionalOffsetDirectional.bottomEnd,
firstChild: new SizedBox(
key: firstKey,
width: 100.0,
height: 100.0,
),
secondChild: new SizedBox(
key: secondKey,
width: 200.0,
height: 200.0,
),
duration: const Duration(milliseconds: 200),
crossFadeState: CrossFadeState.showSecond,
),
),
),
);
await tester.pump(const Duration(milliseconds: 100));
final RenderBox box1 = tester.renderObject(find.byKey(firstKey));
final RenderBox box2 = tester.renderObject(find.byKey(secondKey));
expect(box1.localToGlobal(Offset.zero), const Offset(325.0, 175.0));
expect(box2.localToGlobal(Offset.zero), const Offset(325.0, 175.0));
});
Widget crossFadeWithWatcher({bool towardsSecond: false}) { Widget crossFadeWithWatcher({bool towardsSecond: false}) {
return new AnimatedCrossFade( return new AnimatedCrossFade(
firstChild: const _TickerWatchingWidget(), firstChild: const _TickerWatchingWidget(),
......
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