Switch SlideTransition over to using Offset (#12369)
Previously, we used `Alignment`, which was difficult to understand. Now,
we just use an `Offset` scaled to the child's size, which is much easier
to understand.
diff --git a/examples/flutter_gallery/lib/demo/material/bottom_navigation_demo.dart b/examples/flutter_gallery/lib/demo/material/bottom_navigation_demo.dart
index 63b5791..74651f8 100644
--- a/examples/flutter_gallery/lib/demo/material/bottom_navigation_demo.dart
+++ b/examples/flutter_gallery/lib/demo/material/bottom_navigation_demo.dart
@@ -47,9 +47,9 @@
return new FadeTransition(
opacity: _animation,
child: new SlideTransition(
- position: new AlignmentTween(
- begin: const Alignment(0.0, 0.4), // Slightly down.
- end: Alignment.center,
+ position: new Tween<Offset>(
+ begin: const Offset(0.0, 0.02), // Slightly down.
+ end: Offset.zero,
).animate(_animation),
child: new IconTheme(
data: new IconThemeData(
diff --git a/examples/flutter_gallery/lib/demo/material/drawer_demo.dart b/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
index 85c1e32..f35f1b0 100644
--- a/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
+++ b/examples/flutter_gallery/lib/demo/material/drawer_demo.dart
@@ -25,7 +25,7 @@
AnimationController _controller;
Animation<double> _drawerContentsOpacity;
- Animation<Alignment> _drawerDetailsPosition;
+ Animation<Offset> _drawerDetailsPosition;
bool _showDrawerContents = true;
@override
@@ -39,9 +39,9 @@
parent: new ReverseAnimation(_controller),
curve: Curves.fastOutSlowIn,
);
- _drawerDetailsPosition = new AlignmentTween(
- begin: const Alignment(0.0, -2.0),
- end: Alignment.center,
+ _drawerDetailsPosition = new Tween<Offset>(
+ begin: const Offset(0.0, -1.0),
+ end: Offset.zero,
).animate(new CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart
index 6ad1101..46355ad 100644
--- a/packages/flutter/lib/src/cupertino/route.dart
+++ b/packages/flutter/lib/src/cupertino/route.dart
@@ -10,22 +10,22 @@
const double _kBackGestureWidth = 20.0;
const double _kMinFlingVelocity = 1.0; // Screen widths per second.
-// Fractional offset from offscreen to the right to fully on screen.
-final AlignmentTween _kRightMiddleTween = new AlignmentTween(
- begin: Alignment.centerRight * 2.0,
- end: Alignment.center,
+// Offset from offscreen to the right to fully on screen.
+final Tween<Offset> _kRightMiddleTween = new Tween<Offset>(
+ begin: const Offset(1.0, 0.0),
+ end: Offset.zero,
);
-// Fractional offset from fully on screen to 1/3 offscreen to the left.
-final AlignmentTween _kMiddleLeftTween = new AlignmentTween(
- begin: Alignment.center,
- end: const Alignment(-2.0/3.0, 0.0),
+// Offset from fully on screen to 1/3 offscreen to the left.
+final Tween<Offset> _kMiddleLeftTween = new Tween<Offset>(
+ begin: Offset.zero,
+ end: const Offset(-1.0/3.0, 0.0),
);
-// Fractional offset from offscreen below to fully on screen.
-final AlignmentTween _kBottomUpTween = new AlignmentTween(
- begin: Alignment.bottomCenter * 2.0,
- end: Alignment.center,
+// Offset from offscreen below to fully on screen.
+final Tween<Offset> _kBottomUpTween = new Tween<Offset>(
+ begin: const Offset(0.0, 1.0),
+ end: Offset.zero,
);
// Custom decoration from no shadow to page shadow mimicking iOS page
@@ -318,9 +318,9 @@
super(key: key);
// When this page is coming in to cover another page.
- final Animation<Alignment> _primaryPositionAnimation;
+ final Animation<Offset> _primaryPositionAnimation;
// When this page is becoming covered by another page.
- final Animation<Alignment> _secondaryPositionAnimation;
+ final Animation<Offset> _secondaryPositionAnimation;
final Animation<Decoration> _primaryShadowAnimation;
/// The widget below this widget in the tree.
@@ -361,7 +361,7 @@
),
super(key: key);
- final Animation<Alignment> _positionAnimation;
+ final Animation<Offset> _positionAnimation;
/// The widget below this widget in the tree.
final Widget child;
diff --git a/packages/flutter/lib/src/material/page.dart b/packages/flutter/lib/src/material/page.dart
index e086207..967277d 100644
--- a/packages/flutter/lib/src/material/page.dart
+++ b/packages/flutter/lib/src/material/page.dart
@@ -9,9 +9,9 @@
import 'theme.dart';
// Fractional offset from 1/4 screen below the top to fully on screen.
-final AlignmentTween _kBottomUpTween = new AlignmentTween(
- begin: Alignment.bottomCenter * 0.5,
- end: Alignment.center
+final Tween<Offset> _kBottomUpTween = new Tween<Offset>(
+ begin: const Offset(0.0, 0.25),
+ end: Offset.zero,
);
// Used for Android and Fuchsia.
@@ -26,7 +26,7 @@
)),
super(key: key);
- final Animation<Alignment> _positionAnimation;
+ final Animation<Offset> _positionAnimation;
final Widget child;
@override
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index 3447072..1034460 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -1896,27 +1896,33 @@
/// Applies a translation transformation before painting its child.
///
-/// The translation is expressed as a [Alignment] relative to the
-/// RenderFractionalTranslation box's size. Hit tests will only be detected
-/// inside the bounds of the RenderFractionalTranslation, even if the contents
-/// are offset such that they overflow.
+/// The translation is expressed as a [Offset] scaled to the child's size. For
+/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
+/// translation of one quarter the width of the child.
+///
+/// Hit tests will only be detected inside the bounds of the
+/// [RenderFractionalTranslation], even if the contents are offset such that
+/// they overflow.
class RenderFractionalTranslation extends RenderProxyBox {
/// Creates a render object that translates its child's painting.
///
/// The [translation] argument must not be null.
RenderFractionalTranslation({
- Alignment translation,
+ @required Offset translation,
this.transformHitTests: true,
RenderBox child
- }) : assert(translation == null || (translation.x != null && translation.y != null)),
+ }) : assert(translation != null),
_translation = translation,
super(child);
- /// The translation to apply to the child, relative to the child's center.
- Alignment get translation => _translation;
- Alignment _translation;
- set translation(Alignment value) {
- assert(value == null || (value.x != null && value.y != null));
+ /// The translation to apply to the child, scaled to the child's size.
+ ///
+ /// For example, an [Offset] with a `dx` of 0.25 will result in a horizontal
+ /// translation of one quarter the width of the child.
+ Offset get translation => _translation;
+ Offset _translation;
+ set translation(Offset value) {
+ assert(value != null);
if (_translation == value)
return;
_translation = value;
@@ -1935,11 +1941,9 @@
bool hitTest(HitTestResult result, { Offset position }) {
assert(!debugNeedsLayout);
if (transformHitTests) {
- final double halfWidth = size.width / 2.0;
- final double halfHeight = size.height / 2.0;
position = new Offset(
- position.dx - translation.x * halfWidth,
- position.dy - translation.y * halfHeight,
+ position.dx - translation.dx * size.width,
+ position.dy - translation.dy * size.height,
);
}
return super.hitTest(result, position: position);
@@ -1949,26 +1953,25 @@
void paint(PaintingContext context, Offset offset) {
assert(!debugNeedsLayout);
if (child != null) {
- final double halfWidth = size.width / 2.0;
- final double halfHeight = size.height / 2.0;
super.paint(context, new Offset(
- offset.dx + translation.x * halfWidth,
- offset.dy + translation.y * halfHeight,
+ offset.dx + translation.dx * size.width,
+ offset.dy + translation.dy * size.height,
));
}
}
@override
void applyPaintTransform(RenderBox child, Matrix4 transform) {
- final double halfWidth = size.width / 2.0;
- final double halfHeight = size.height / 2.0;
- transform.translate(translation.x * halfWidth, translation.y * halfHeight);
+ transform.translate(
+ translation.dx * size.width,
+ translation.dy * size.height,
+ );
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
- description.add(new DiagnosticsProperty<Alignment>('translation', translation));
+ description.add(new DiagnosticsProperty<Offset>('translation', translation));
description.add(new DiagnosticsProperty<bool>('transformHitTests', transformHitTests));
}
}
diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart
index 5beb4e6..3a455cf 100644
--- a/packages/flutter/lib/src/widgets/basic.dart
+++ b/packages/flutter/lib/src/widgets/basic.dart
@@ -987,8 +987,15 @@
}
}
-/// A widget that applies a translation expressed as a fraction of the box's
-/// size before painting its child.
+/// Applies a translation transformation before painting its child.
+///
+/// The translation is expressed as a [Offset] scaled to the child's size. For
+/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
+/// translation of one quarter the width of the child.
+///
+/// Hit tests will only be detected inside the bounds of the
+/// [FractionalTranslation], even if the contents are offset such that
+/// they overflow.
class FractionalTranslation extends SingleChildRenderObjectWidget {
/// Creates a widget that translates its child's painting.
///
@@ -1001,8 +1008,11 @@
}) : assert(translation != null),
super(key: key, child: child);
- /// The translation to apply to the child, relative to the child's center.
- final Alignment translation;
+ /// The translation to apply to the child, scaled to the child's size.
+ ///
+ /// For example, an [Offset] with a `dx` of 0.25 will result in a horizontal
+ /// translation of one quarter the width of the child.
+ final Offset translation;
/// Whether to apply the translation when performing hit tests.
final bool transformHitTests;
diff --git a/packages/flutter/lib/src/widgets/dismissible.dart b/packages/flutter/lib/src/widgets/dismissible.dart
index e83245f..491f2c2 100644
--- a/packages/flutter/lib/src/widgets/dismissible.dart
+++ b/packages/flutter/lib/src/widgets/dismissible.dart
@@ -135,21 +135,19 @@
super(reclip: moveAnimation);
final Axis axis;
- final Animation<Alignment> moveAnimation;
+ final Animation<Offset> moveAnimation;
@override
Rect getClip(Size size) {
assert(axis != null);
switch (axis) {
case Axis.horizontal:
- final double halfWidth = size.width / 2.0;
- final double offset = halfWidth + moveAnimation.value.x * halfWidth;
+ final double offset = moveAnimation.value.dx * size.width;
if (offset < 0)
return new Rect.fromLTRB(size.width + offset, 0.0, size.width, size.height);
return new Rect.fromLTRB(0.0, 0.0, offset, size.height);
case Axis.vertical:
- final double halfHeight = size.height / 2.0;
- final double offset = halfHeight + moveAnimation.value.y * halfHeight;
+ final double offset = moveAnimation.value.dy * size.height;
if (offset < 0)
return new Rect.fromLTRB(0.0, size.height + offset, size.width, size.height);
return new Rect.fromLTRB(0.0, 0.0, size.width, offset);
@@ -177,7 +175,7 @@
}
AnimationController _moveController;
- Animation<Alignment> _moveAnimation;
+ Animation<Offset> _moveAnimation;
AnimationController _resizeController;
Animation<double> _resizeAnimation;
@@ -270,10 +268,10 @@
}
void _updateMoveAnimation() {
- final double end = _dragExtent.sign * 2.0;
- _moveAnimation = new AlignmentTween(
- begin: Alignment.center,
- end: _directionIsXAxis ? new Alignment(end, 0.0) : new Alignment(0.0, end),
+ final double end = _dragExtent.sign;
+ _moveAnimation = new Tween<Offset>(
+ begin: Offset.zero,
+ end: _directionIsXAxis ? new Offset(end, 0.0) : new Offset(0.0, end),
).animate(_moveController);
}
diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart
index 14e0307..fc47c43 100644
--- a/packages/flutter/lib/src/widgets/routes.dart
+++ b/packages/flutter/lib/src/widgets/routes.dart
@@ -632,9 +632,9 @@
/// Widget child,
/// ) {
/// return new SlideTransition(
- /// position: new AlignmentTween(
- /// begin: Alignment.bottomCenter,
- /// end: Alignment.topCenter,
+ /// position: new Tween<Offset>(
+ /// begin: const Offset(0.0, 1.0),
+ /// end: Offset.zero,
/// ).animate(animation),
/// child: child, // child is the value returned by pageBuilder
/// );
@@ -670,13 +670,13 @@
/// ) {
/// return new SlideTransition(
/// position: new AlignmentTween(
- /// begin: Alignment.bottomCenter,
- /// end: Alignment.topCenter,
+ /// begin: const Offset(0.0, 1.0),
+ /// end: Offset.zero,
/// ).animate(animation),
/// child: new SlideTransition(
- /// position: new AlignmentTween(
- /// begin: Alignment.topCenter,
- /// end: Alignment.bottomCenter,
+ /// position: new TweenOffset(
+ /// begin: Offset.zero,
+ /// end: const Offset(0.0, 1.0),
/// ).animate(secondaryAnimation),
/// child: child,
/// ),
diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart
index f982b49..8b11b3d 100644
--- a/packages/flutter/lib/src/widgets/transitions.dart
+++ b/packages/flutter/lib/src/widgets/transitions.dart
@@ -97,22 +97,28 @@
}
/// Animates the position of a widget relative to its normal position.
+///
+/// The translation is expressed as a [Offset] scaled to the child's size. For
+/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
+/// translation of one quarter the width of the child.
class SlideTransition extends AnimatedWidget {
/// Creates a fractional translation transition.
///
/// The [position] argument must not be null.
const SlideTransition({
Key key,
- @required Animation<Alignment> position,
+ @required Animation<Offset> position,
this.transformHitTests: true,
this.child,
- }) : super(key: key, listenable: position);
+ }) : assert(position != null),
+ super(key: key, listenable: position);
/// The animation that controls the position of the child.
///
- /// If the current value of the position animation is (dx, dy), the child will
- /// be translated horizontally by width * dx and vertically by height * dy.
- Animation<Alignment> get position => listenable;
+ /// If the current value of the position animation is `(dx, dy)`, the child
+ /// will be translated horizontally by `width * dx` and vertically by
+ /// `height * dy`.
+ Animation<Offset> get position => listenable;
/// Whether hit testing should be affected by the slide animation.
///