1)PositionedTransition
是AnimatedWidget的子类,跟AnimatedBuilder一样。主要是为了在使用动画的过程中减少不必要的Widget对象的创建工作,提高效率。
2)该类持有了一个Animation<RelativeRect>的引用rect
3)在build构建widget的时候使用了动画rect.value,在这里这个value就是RelativeRect对象。
那么这个RelativeRect对象是什么呢?在回答这个问题之前先来看看官方文档给的例子,通过这个视频可以看出PositionedTranstion是用来干嘛的。
width="560" height="315" src=" https://flutter.github.io/assets-for-api-docs/assets/widgets/positioned_transition.mp4" allowfullscreen="">
显而易见,PositionedTranstion通过一个特定的动画Animation<RelativeRect>将Widget的位置从动画的生命周期的起始位置移到结束位置。而这个位置信息就是RelativeRect来表示,Relative相对的意思,相对谁?相对于某个Widget,而不是相对于坐标原点。RelativeRect
有四个属性:
//widget的左边框距离此RelativeRect的左边框的距离
final double left;
//widget的上边框距离此RelativeRect的上边框的距离
final double top;
//widget的右边框距离此RelativeRect的右边框的距离
final double right;
//widget的底边框距离此RelativeRect的底部边框的距离
final double bottom;
所以如果我们想让一个widget的位置(上下左右)距离RelativeRect都是100的话,就要这么写:
RelativeRect.fromLTRB(
100.0,///l child.left 到此left边的距离为0
100.0,///t child.top的距离到此rect.top的距离为0
100.0,///r child.right的距离到此rect.rignt的距离为0
100.0,///t child.bottom到此rect.bottom边的距离为100
)
- 创建自定义转场类
import 'package:flutter/material.dart';
class ScaleRoute extends PageRouteBuilder {
final Widget widget;
final RelativeRect rect;
ScaleRoute({@required this.widget, @required this.rect}) :
super(pageBuilder: (BuildContext context,Animation<double> animation, Animation<double> secondaryAnimation) { return widget; },
transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return Stack(
children: [
Container(),
PositionedTransition(
child: child,
rect: RelativeRectTween(
begin: rect,
end: RelativeRect.fromLTRB(0.0, 0.0, 0.0, 0.0),
).animate(animation),
),
],
);
},
transitionDuration: Duration(milliseconds: 300),
);
}
- 使用方法
var rect = RelativeRect.fromLTRB(
horizontalOffset, topOffset, horizontalOffset, bottomOffset);
Navigator.push(
context,
ScaleRoute(
rect: rect,
widget: DetailScreen(
taskId: task.id,
heroIds: heroIds,
),
),
// MaterialPageRoute(
// builder: (context) => DetailScreen(
// taskId: task.id,
// heroIds: heroIds,
// ),
// ),
);
运行效果如下:
注意:
从上面代码可以看出PositionedTransition必须作为
Stack这个widget的child Widget
来使用