1. 普通的动画 Alpha Scale Slide Rotate
普通控件动画创建步骤:
1. AnimationController
2. Animation 通过Tween创建动画
3. 将动画 Animation 设置给 RotateAnimation--> Widget
4. controller.repeat(), forward(), reverse(),
import 'package:flutter/material.dart';
//https://blog.csdn.net/zhakesipailuo/article/details/89882968
class WidgetAnimation extends StatefulWidget {
@override
_WidgetAnimationState createState() => _WidgetAnimationState();
}
//注意:在创建AnimationController的时候,需要混入TickerProviderStateMixin
class _WidgetAnimationState extends State<WidgetAnimation>
with TickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller) // Tween 线性动画 CurvedAnimation 非线性动画
..addListener(() {
setState(() {});
});
_controller.forward();
//forward() 开始动画
//repeat() 重复动画
//reverse() 反向执行动画
//AnimatedBuilder 也可以创建动画Widget 这样的效果是缩小了build范围 有优化效果
//AnimatedWidget 可以创建动画Widget
}
// RotateTransition turns: _animation
// ScaleTransition scale: _animation
// FadeTransition opacity: _animation,
// SlideTransition position: _animation
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Widget动画'),
),
body: Container(
alignment: Alignment.center,
child: Container(
child: FadeTransition(
opacity: _animation,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
),
),
),
),
);
}
}
2. 使用 AnimatedBuilder 来创建动画
import 'package:flutter/material.dart';
//AnimatedBuilder来创建具有动画效果的Widget
class AnimatedBuilderPage extends StatefulWidget {
@override
_AnimatedBuilderPageState createState() => _AnimatedBuilderPageState();
}
class _AnimatedBuilderPageState extends State<AnimatedBuilderPage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: const Duration(seconds: 3));
//_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_controller);
//CurvedAnimation需要配合Tween合作才能生效
//_animation = CurvedAnimation(parent: _controller, curve: Curves.bounceInOut);
//_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_animation); //CurvedAnimation 是作用与Tween上的,改变变化速率
_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AnimatedBuilder'),
),
body: Container(
child: Center(
child: AnimatedBuilder(
animation: _animation,
// 注意:这里需要指定child,否则会看不到效果 这里指定了图片为child
child: Image.asset('images/lovely_girl.jpg'),
builder: (BuildContext context, Widget child) {
return Container(
width: _animation.value,
height: _animation.value,
child: child,
);
},
),
),
),
);
}
@override
void dispose() {
//2. 注意:需要这里的_controller.dispose() 调用需要在super.dispose()之前调用
_controller.dispose();
super.dispose();
}
}
3. 继承 AnimatedWidget 实现动画
import 'package:flutter/material.dart';
//创建继承自AnimatedWidget的具有动画效果的Widget
class AnimatedWidgetPage extends StatefulWidget {
@override
_AnimatedWidgetPageState createState() => _AnimatedWidgetPageState();
}
class _AnimatedWidgetPageState extends State<AnimatedWidgetPage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
_animation = Tween<double>(begin: 0.0, end: 300).animate(_controller);
_animation.addStatusListener((status) {
if (status == AnimationStatus.forward) {
// 动画正在正向执行
print('forward....');
} else if (status == AnimationStatus.completed) {
// 动画在中点结束
print('completed....');
} else if (status == AnimationStatus.reverse) {
// 动画正在反向执行
print('reverse....');
} else if (status == AnimationStatus.dismissed) {
//动画在起点结束
print('dismissed...');
}
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AnimatedWidget'),
),
body: Container(
child: Center(
child: GrowableWidget(
animation: _animation,
),
),
),
);
}
@override
void dispose() {
super.dispose();
}
}
class GrowableWidget extends AnimatedWidget {
GrowableWidget({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
@override
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return Center(
child: Image.asset(
'images/lovely_girl.jpg',
width: animation.value,
height: animation.value,
),
);
}
}
4. Hero 动画 Hero
import 'package:flutter/material.dart';
import 'package:flutter_widgets/animation/hero_animation_next_page.dart';
class HeroAnimationPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HeroAnimation'),
),
body: Stack(
children: [
Container(
margin: EdgeInsets.only(top: 400),
alignment: Alignment.topCenter,
child: Hero(
tag: 'avatar',
child: ClipOval(
child: Image.asset(
'images/lovely_girl.jpg',
fit: BoxFit.cover,
width: 100,
height: 100,
),
)),
),
Align(
alignment: Alignment.topCenter,
child: Container(
margin: EdgeInsets.only(left: 10, right: 10),
child: MaterialButton(
color: Colors.blue,
//minWidth: double.infinity,
onPressed: () {
Navigator.of(context).push(PageRouteBuilder(pageBuilder:
(BuildContext context, Animation animation,
Animation secondaryAnimation) {
return new FadeTransition(
opacity: animation,
child: HeroAnimationNextPage(),
);
}));
},
child: Text('点击跳转到下一个Hero页面', style: TextStyle(color: Colors.white),),
),
),
)
],
),
);
}
}
import 'package:flutter/material.dart';
class HeroAnimationNextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HeroAnimationNext'),
),
body: Stack(
children: [
Container(
margin: EdgeInsets.only(top: 200),
alignment: Alignment.topCenter,
child: Hero(
tag: 'avatar', // 和上一个Hero页面一样,也需要相同的tag来做标记,同时用Hero来包裹
child: ClipOval(
child: Image.asset(
'images/lovely_girl.jpg',
fit: BoxFit.cover,
width: 100,
height: 100,
),
)),
),
Align(
alignment: Alignment.topCenter,
child: Container(
margin: EdgeInsets.only(left: 10, right: 10),
child: MaterialButton(
color: Colors.blue,
minWidth: double.infinity,
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'点击跳转到上一个Hero页面',
style: TextStyle(color: Colors.white),
),
),
),
)
],
),
);
}
}
5. 路由动画 利用PageRouterBuilder 来构建路由,用FadeTransition来包裹跳转的Page
import 'package:flutter/material.dart';
import 'package:flutter_widgets/animation/route_next_page.dart';
//路由动画
class RouteAnimationPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Route动画'),
),
body: Container(
child: Column(
children: [
Container(
margin: EdgeInsets.only(left: 10, right: 10),
child: MaterialButton(
minWidth: double.infinity,
color: Colors.blue,
onPressed: () {
Navigator.of(context).push(PageRouteBuilder(
transitionDuration:Duration(microseconds: 2000), // 动画时间为500ms
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
return FadeTransition(
opacity: animation,
child: RouteNextPage(),
);
}));
},
child: Text(
'跳转到下一个页面',
style: TextStyle(color: Colors.white),
),
),
)
],
)),
);
}
}
import 'package:flutter/material.dart';
class RouteNextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Route动画下一页面'),
),
body: Container(
child: Column(
children: [
Container(
margin: EdgeInsets.only(left: 10, right: 10),
child: MaterialButton(
minWidth: double.infinity,
color: Colors.blue,
onPressed: () {
Navigator.of(context).pop();
},
child: Text('退出本页面', style: TextStyle(color: Colors.white),),
),
)
],
),
),
);
}
}