mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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.
This commit is contained in:
parent
31b6ac049c
commit
6128f48c80
@ -47,9 +47,9 @@ class NavigationIconView {
|
||||
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(
|
||||
|
@ -25,7 +25,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
|
||||
|
||||
AnimationController _controller;
|
||||
Animation<double> _drawerContentsOpacity;
|
||||
Animation<Alignment> _drawerDetailsPosition;
|
||||
Animation<Offset> _drawerDetailsPosition;
|
||||
bool _showDrawerContents = true;
|
||||
|
||||
@override
|
||||
@ -39,9 +39,9 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
|
||||
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,
|
||||
|
@ -10,22 +10,22 @@ import 'package:flutter/widgets.dart';
|
||||
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 @@ class CupertinoPageTransition extends StatelessWidget {
|
||||
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 @@ class CupertinoFullscreenDialogTransition extends StatelessWidget {
|
||||
),
|
||||
super(key: key);
|
||||
|
||||
final Animation<Alignment> _positionAnimation;
|
||||
final Animation<Offset> _positionAnimation;
|
||||
|
||||
/// The widget below this widget in the tree.
|
||||
final Widget child;
|
||||
|
@ -9,9 +9,9 @@ import 'package:flutter/widgets.dart';
|
||||
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 @@ class _MountainViewPageTransition extends StatelessWidget {
|
||||
)),
|
||||
super(key: key);
|
||||
|
||||
final Animation<Alignment> _positionAnimation;
|
||||
final Animation<Offset> _positionAnimation;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
|
@ -1896,27 +1896,33 @@ class RenderFittedBox extends RenderProxyBox {
|
||||
|
||||
/// 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 @@ class RenderFractionalTranslation extends RenderProxyBox {
|
||||
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 @@ class RenderFractionalTranslation extends RenderProxyBox {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -987,8 +987,15 @@ class FittedBox extends SingleChildRenderObjectWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 @@ class FractionalTranslation extends SingleChildRenderObjectWidget {
|
||||
}) : 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;
|
||||
|
@ -135,21 +135,19 @@ class _DismissibleClipper extends CustomClipper<Rect> {
|
||||
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 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
|
||||
}
|
||||
|
||||
AnimationController _moveController;
|
||||
Animation<Alignment> _moveAnimation;
|
||||
Animation<Offset> _moveAnimation;
|
||||
|
||||
AnimationController _resizeController;
|
||||
Animation<double> _resizeAnimation;
|
||||
@ -270,10 +268,10 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -632,9 +632,9 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
|
||||
/// 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 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
|
||||
/// ) {
|
||||
/// 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,
|
||||
/// ),
|
||||
|
@ -97,22 +97,28 @@ class _AnimatedState extends State<AnimatedWidget> {
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user