最近比较忙,很少发文章了。今天抽空把Hero的转场组件共享说一下 顺便发个转场的动画福利类,可以定义转场的时间,曲线,别客气,随便拿去用。 废话不多说,先看图:
- 1.透明:
FadeRouter
- 2.缩放:
ScaleRouter
- 3.旋转:
RotateRouter
- 4.透明 缩放 旋转
- 5.右--->左:
Right2LeftRouter
- 6.左--->右:
Left2RightRouter
- 7.上--->下:
Top2BottomRouter
- 8.下--->上:
Bottom2TopRouter
Hero元素共享
也许上面吸引你的不是界面跳转的动画,而是那个头像神奇般的轨迹。下面就来说一下如何实现。
起始页:OriginPage
代码语言:javascript复制class OriginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var hero= Hero(//----定义一个Hero,并添加tag标签,此中组件共享
tag: 'user-head',
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30)),
child: Image.asset(
"images/mani.jpg",width: 60,height: 60,fit: BoxFit.cover,
),
),
);
var container= Container(//容器,没啥好说的
alignment: Alignment(-0.8, -0.8),
child: hero,
width: 250,
height: 250*0.618,
decoration: BoxDecoration(//添加渐变色
gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])
),);
return Scaffold(
body: Center(//点击跳转
child: GestureDetector(child: Card(elevation:5,child:container ,),onTap: (){
_toNext(context);
},),
),
);
}
void _toNext(context) {//跳转路由
Navigator.push(
context,
// FadeRouter(child:TargetPage()),
// ScaleRouter(child:TargetPage()),
// RotateRouter(child:TargetPage()),
// ScaleFadeRotateRouter(child:TargetPage()),
// Right2LeftRouter(child:TargetPage()),
// Left2RightRouter(child:TargetPage()),
// Top2BottomRouter(child:TargetPage()),
Bottom2TopRouter(child:TargetPage()),//跳转 动画
);
}
}
目标页:TargetPage
代码语言:javascript复制class TargetPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var hero=Hero(//----定义一个Hero,为其添加标签,两个标签相同,则可以共享
tag: 'user-head',
child: Padding(
padding: EdgeInsets.all(16.0),
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 72.0,
backgroundImage: AssetImage(
"images/mani.jpg",
),
),
),
);
var touch=InkWell(onTap: (){
Navigator.of(context).pop();
},child: hero,);
return Scaffold(
appBar: AppBar(leading:touch ,),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])
),
),
);
}
}
关于createRectTween属性
代码语言:javascript复制在回调中会给两个初始和结束的两个矩形,可以进行矩形动画来控制共享组件的区域,如下图在目标页:
var height=MediaQuery.of(context).size.height;
var width=MediaQuery.of(context).size.width;
var size=min(height,width);
var hero=Hero(//----定义一个Hero,为其添加标签,两个标签相同,则可以共享
createRectTween: ((r1,r2){
return RectTween(begin: Rect.fromLTWH(size/2,0, size, size),end: r2);
}),
另外还有个要点:同一页面不能出现多处同名Hero
福利时间:路由动画工具
代码语言:javascript复制使用方法看上面的路由跳转处,当然你也可以根据下面的定制更酷炫的跳转效果。
import 'package:flutter/cupertino.dart';
//缩放路由动画
class ScaleRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
ScaleRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
: super(
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionDuration: Duration(milliseconds: duration_ms),
transitionsBuilder: (context, a1, a2, child) =>
ScaleTransition(
scale: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: child,
),
);
}
//渐变透明路由动画
class FadeRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
FadeRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
: super(
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionDuration: Duration(milliseconds: duration_ms),
transitionsBuilder: (context, a1, a2, child) =>
FadeTransition(
opacity: Tween(begin: 0.1, end: 1.0).animate(
CurvedAnimation(parent: a1, curve:curve,)),
child: child,
));
}
//旋转路由动画
class RotateRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
RotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})
: super(
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionDuration: Duration(milliseconds: duration_ms),
transitionsBuilder: (context, a1, a2, child) =>
RotationTransition(
turns: Tween(begin: 0.1, end: 1.0).animate(
CurvedAnimation(parent: a1, curve:curve,)),
child: child,
));
}
//右--->左
class Right2LeftRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
Right2LeftRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
:super(
transitionDuration:Duration(milliseconds: duration_ms),
pageBuilder:(ctx,a1,a2){return child;},
transitionsBuilder:(ctx,a1,a2,Widget child,) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0),).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: child
);
});
}
//左--->右
class Left2RightRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
List<int> mapper;
Left2RightRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
:assert(true),super(
transitionDuration:Duration(milliseconds: duration_ms),
pageBuilder:(ctx,a1,a2){return child;},
transitionsBuilder:(ctx,a1,a2,Widget child,) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(-1.0, 0.0), end: Offset(0.0, 0.0),).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: child
);
});
}
//上--->下
class Top2BottomRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
Top2BottomRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
:super(
transitionDuration:Duration(milliseconds: duration_ms),
pageBuilder:(ctx,a1,a2){return child;},
transitionsBuilder:(ctx,a1,a2,Widget child,) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0,-1.0), end: Offset(0.0, 0.0),).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: child
);
});
}
//下--->上
class Bottom2TopRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
Bottom2TopRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})
:super(
transitionDuration:Duration(milliseconds: duration_ms),
pageBuilder:(ctx,a1,a2){return child;},
transitionsBuilder:(ctx,a1,a2,Widget child,) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0),).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: child
);
});
}
//缩放 透明 旋转路由动画
class ScaleFadeRotateRouter<T> extends PageRouteBuilder<T> {
final Widget child;
final int duration_ms;
final Curve curve;
ScaleFadeRotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn}) : super(
transitionDuration: Duration(milliseconds: duration_ms),
pageBuilder: (ctx, a1, a2)=>child,//页面
transitionsBuilder: (ctx, a1, a2, Widget child,) {//构建动画
return RotationTransition(//旋转动画
turns: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: a1,
curve: curve,
)),
child: ScaleTransition(//缩放动画
scale: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: a1, curve: curve)),
child: FadeTransition(opacity://透明度动画
Tween(begin: 0.5, end: 1.0).animate(CurvedAnimation(parent: a1, curve: curve)),
child: child,),
),
);
});
}
//无动画
class NoAnimRouter<T> extends PageRouteBuilder<T> {
final Widget page;
NoAnimRouter(this.page)
: super(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionDuration: Duration(milliseconds: 0),
transitionsBuilder:
(context, animation, secondaryAnimation, child) => child);
}