Unverified Commit b989428f authored by Valentin Vignal's avatar Valentin Vignal Committed by GitHub

Add `SizeTransition.fixedCrossAxisSizeFactor` (#134659)

Fixes https://github.com/flutter/flutter/issues/134654
parent f38244f0
......@@ -441,8 +441,10 @@ class SizeTransition extends AnimatedWidget {
this.axis = Axis.vertical,
required Animation<double> sizeFactor,
this.axisAlignment = 0.0,
this.fixedCrossAxisSizeFactor,
this.child,
}) : super(listenable: sizeFactor);
}) : assert(fixedCrossAxisSizeFactor == null || fixedCrossAxisSizeFactor >= 0.0),
super(listenable: sizeFactor);
/// [Axis.horizontal] if [sizeFactor] modifies the width, otherwise
/// [Axis.vertical].
......@@ -471,6 +473,14 @@ class SizeTransition extends AnimatedWidget {
/// A value of 0.0 (the default) indicates the center for either [axis] value.
final double axisAlignment;
/// The factor by which to multiply the cross axis size of the child.
///
/// If the value of [fixedCrossAxisSizeFactor] is less than one, the child
/// will be clipped along the appropriate axis.
///
/// If `null` (the default), the cross axis size is as large as the parent.
final double? fixedCrossAxisSizeFactor;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
......@@ -487,8 +497,8 @@ class SizeTransition extends AnimatedWidget {
return ClipRect(
child: Align(
alignment: alignment,
heightFactor: axis == Axis.vertical ? math.max(sizeFactor.value, 0.0) : null,
widthFactor: axis == Axis.horizontal ? math.max(sizeFactor.value, 0.0) : null,
heightFactor: axis == Axis.vertical ? math.max(sizeFactor.value, 0.0) : fixedCrossAxisSizeFactor,
widthFactor: axis == Axis.horizontal ? math.max(sizeFactor.value, 0.0) : fixedCrossAxisSizeFactor,
child: child,
),
);
......
......@@ -244,6 +244,7 @@ void main() {
textDirection: TextDirection.ltr,
child: SizeTransition(
sizeFactor: animation,
fixedCrossAxisSizeFactor: 2.0,
child: const Text('Ready'),
),
);
......@@ -252,18 +253,22 @@ void main() {
final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
expect(actualPositionedBox.heightFactor, 0.0);
expect(actualPositionedBox.widthFactor, 2.0);
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.0);
expect(actualPositionedBox.widthFactor, 2.0);
controller.value = 0.75;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.5);
expect(actualPositionedBox.widthFactor, 2.0);
controller.value = 1.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 2.0);
});
testWidgetsWithLeakTracking('SizeTransition clamps negative size factors - horizontal axis', (WidgetTester tester) async {
......@@ -275,6 +280,7 @@ void main() {
child: SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
fixedCrossAxisSizeFactor: 1.0,
child: const Text('Ready'),
),
);
......@@ -283,18 +289,139 @@ void main() {
final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
expect(actualPositionedBox.widthFactor, 0.0);
expect(actualPositionedBox.heightFactor, 1.0);
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.widthFactor, 0.0);
expect(actualPositionedBox.heightFactor, 1.0);
controller.value = 0.75;
await tester.pump();
expect(actualPositionedBox.widthFactor, 0.5);
expect(actualPositionedBox.heightFactor, 1.0);
controller.value = 1.0;
await tester.pump();
expect(actualPositionedBox.widthFactor, 1.0);
expect(actualPositionedBox.heightFactor, 1.0);
});
testWidgetsWithLeakTracking('SizeTransition with fixedCrossAxisSizeFactor should size its cross axis from its children - vertical axis', (WidgetTester tester) async {
final AnimationController controller = AnimationController(vsync: const TestVSync());
final Animation<double> animation = Tween<double>(begin: 0, end: 1.0).animate(controller);
const Key key = Key('key');
final Widget widget = Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
key: key,
child: SizeTransition(
sizeFactor: animation,
fixedCrossAxisSizeFactor: 1.0,
child: const SizedBox.square(dimension: 100),
),
),
),
);
await tester.pumpWidget(widget);
final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
expect(actualPositionedBox.heightFactor, 0.0);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size(100, 0));
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.0);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size(100, 0));
controller.value = 0.5;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.5);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size(100, 50));
controller.value = 1.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size.square(100));
controller.value = 0.5;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.5);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size(100, 50));
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 0.0);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size(100, 0));
});
testWidgetsWithLeakTracking('SizeTransition with fixedCrossAxisSizeFactor should size its cross axis from its children - horizontal axis', (WidgetTester tester) async {
final AnimationController controller = AnimationController(vsync: const TestVSync());
final Animation<double> animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller);
const Key key = Key('key');
final Widget widget = Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
key: key,
child: SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
fixedCrossAxisSizeFactor: 1.0,
child: const SizedBox.square(dimension: 100),
),
),
),
);
await tester.pumpWidget(widget);
final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 0.0);
expect(tester.getSize(find.byKey(key)), const Size(0, 100));
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 0.0);
expect(tester.getSize(find.byKey(key)), const Size(0, 100));
controller.value = 0.5;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 0.5);
expect(tester.getSize(find.byKey(key)), const Size(50, 100));
controller.value = 1.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 1.0);
expect(tester.getSize(find.byKey(key)), const Size.square(100));
controller.value = 0.5;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 0.5);
expect(tester.getSize(find.byKey(key)), const Size(50, 100));
controller.value = 0.0;
await tester.pump();
expect(actualPositionedBox.heightFactor, 1.0);
expect(actualPositionedBox.widthFactor, 0.0);
expect(tester.getSize(find.byKey(key)), const Size(0, 100));
});
testWidgetsWithLeakTracking('MatrixTransition animates', (WidgetTester tester) async {
......
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