本篇文章已授权微信公众号 YYGeeker
独家发布转载请标明出处
1、简介
AnimatedContainer
表示一个动画容器,只要更改容器的值,就能表现出对应的动画效果2、构造函数
AnimatedContainer({
Key key,
this.alignment,
this.padding,
Color color,
Decoration decoration,
this.foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
this.margin,
this.transform,
this.child,
Curve curve = Curves.linear,
@required Duration duration,
})
alignment
表示子元素child相对于容器的对其方式AnimatedContainer
中默认位于居中位置child
当前的aligament方式,则为(0,0)AnimatedContainer
的四个顶点,则为(-1,-1)(-1,1)(1,-1)(1,1)AlignmentDirectional
控制child在X、Y轴的偏移,decoration
也能设置背景色,两者不可共存color
也能设置背景色,两者不可共存decoration
或color
的颜色3、例子
通过定时器改变容器的大小,边框,边距等属性,让容器动起来
var time = 0;
var _color = Colors.red[200];
var _borderColor = Colors.transparent;
var _width = 200.0;
var _height = 200.0;
var _borderWidth = 0.0;
var _scaleX = 1.0;
var _scaleY = 1.0;
var _rotate = 0.0;
var _padding = 0.0;
var _margin = 0.0;
var _alignmentY = 0.0;
class WeWidgetState extends State {
WeWidgetState() {
Timer.periodic(Duration(milliseconds: 1000), (timer) {
setState(() {
switch (time % 10) {
case 0:
_width = 300;
_height = 100;
break;
case 1:
_width = 100;
_height = 300;
_borderWidth = 4.0;
_borderColor = Colors.brown[200];
break;
case 2:
_borderWidth = 8.0;
_borderColor = Colors.pink[200];
_color = Colors.blue[200];
break;
case 3:
_width = 300;
_height = 300;
_color = Colors.deepPurple[200];
break;
case 4:
_scaleX = 0.2;
_scaleY = 0.2;
break;
case 5:
_scaleX = 0.5;
_scaleY = 0.5;
_rotate = math.pi / 6;
break;
case 6:
_scaleX = 1.0;
_scaleY = 1.0;
_rotate = 0.0;
_padding = 200.0;
break;
case 7:
_padding = 0.0;
break;
case 8:
_margin = 80.0;
_alignmentY = 0.5;
break;
case 9:
_margin = 0.0;
_alignmentY = 0.0;
break;
}
time++;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day6"),
),
resizeToAvoidBottomPadding: false,
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: [
AnimatedContainer(
transform: Matrix4.identity().scaled(_scaleX, _scaleY)
..rotateZ(_rotate),
alignment: AlignmentDirectional(0.0, _alignmentY),
constraints: BoxConstraints(
minWidth: 0.0,
minHeight: 0.0,
maxWidth: 500.0,
maxHeight: 500.0,
),
margin: EdgeInsets.only(left: _margin),
padding: EdgeInsets.only(left: _padding),
width: _width,
height: _height,
duration: Duration(milliseconds: 1000),
curve: Curves.fastOutSlowIn,
child: Icon(
Icons.android,
color: Colors.lightGreenAccent,
size: 40,
),
foregroundDecoration: BoxDecoration(
border: Border.all(
color: _borderColor,
width: _borderWidth,
),
),
//color 和 decoration两者不可共存
//color: _color,
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: _color,
offset: Offset(5.0, 5.0),
blurRadius: 6.0,
)
],
),
),
],
);
}
}
1、简介
AnimatedCrossFade
存放着两个动画的容器,只要切换动画的状态,就能表现出对应的动画效果AnimatedCrossFade
本质就是一个Stack分别存放有两个组件和两个动画2、构造函数
const AnimatedCrossFade({
Key key,
@required this.firstChild,
@required this.secondChild,
this.firstCurve = Curves.linear,
this.secondCurve = Curves.linear,
this.sizeCurve = Curves.linear,
this.alignment = Alignment.topCenter,
@required this.crossFadeState,
@required this.duration,
this.layoutBuilder = defaultLayoutBuilder,
})
3、例子
通过定时器更改变量的值,让控件切换布局,从而开启动画
var time = 0;
var _first = true;
class WeWidgetState extends State {
WeWidgetState() {
Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
switch (time % 4) {
case 0:
_first = false;
break;
case 2:
_first = true;
break;
}
time++;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day7"),
),
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: [
AnimatedCrossFade(
//layoutBuilder: ,
alignment: AlignmentDirectional(0.0, 1.0),
duration: Duration(seconds: 1),
firstCurve: Curves.fastOutSlowIn,
secondCurve: Curves.fastOutSlowIn,
sizeCurve: Curves.fastOutSlowIn,
firstChild: FlutterLogo(
style: FlutterLogoStyle.horizontal,
size: 100.0,
),
secondChild: FlutterLogo(
style: FlutterLogoStyle.stacked,
size: 200.0,
),
crossFadeState:
_first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
],
);
}
}
1、简介
2、构造函数
const Hero({
Key key,
@required this.tag,
this.createRectTween,
this.flightShuttleBuilder,
this.placeholderBuilder,
this.transitionOnUserGestures = false,
@required this.child,
})
3、例子
设置点击加号图标跳转到太阳图标的页面,在跳转的时候用相机快门图标做轨迹运动,同时会有加载占位符
class WeWidgetState extends State<WeWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day8"),
),
body: GestureDetector(
child: _buildColumn(),
onTap: () {
_pushToNewPage();
},
),
);
}
Widget _buildColumn() {
return Hero(
tag: "mmm",
transitionOnUserGestures: true,
placeholderBuilder: (context, size, widget) {
return CircularProgressIndicator();
},
flightShuttleBuilder: (flightContext, animation, flightDirection,
fromHeroContext, toHeroContext) {
return Icon(
Icons.camera,
size: 70.0,
);
},
child: Icon(
Icons.add,
size: 70.0,
),
);
}
void _pushToNewPage() {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return Scaffold(
appBar: AppBar(
title: Text('Hero'),
),
body: Center(
child: Hero(
tag: "mmm",
child: Icon(
Icons.wb_sunny,
size: 70.0,
),
),
));
}),
);
}
}
1、简介
AnimatedBuilder
表示一个动画的构造器,可以通过控制器去控制动画值改变,从而控制动画2、构造函数
AnimatedBuilder({
Key key,
Listenable animation,
this.builder,
this.child,
})
3、例子
我们可以将常用属性包装成一个控件
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
child: this.child,
animation: animation,
builder: (BuildContext context, Widget child) {
return Container(
height: animation.value,
width: animation.value,
child: child,
);
},
),
);
}
}
动画属性值的变化需要AnimationController
来控制,通过CurvedAnimation
设置其插值器,通过Tween
设置其值的变化范围
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//尝试扩展或实现num时,除int或double之外的任何类型都是编译时错误
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
@override
void initState() {
super.initState();
//动画控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
//动画插值器
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
//动画变化范围
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve);
//启动动画
_controller.forward();
}
}
通过addStatusListener
监听动画状态的变化和通过addListener
监听动画值的变化
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//尝试扩展或实现num时,除int或double之外的任何类型都是编译时错误
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
double _animationValue;
AnimationStatus _state;
@override
void initState() {
super.initState();
//动画控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
//动画插值器
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
//动画变化范围
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve)
..addListener(() {
setState(() {
//记录变化的值
_animationValue = _animation.value;
});
})
..addStatusListener((AnimationStatus state) {
//如果动画已完成,就反转动画
if (state == AnimationStatus.completed) {
_controller.reverse();
} else if (state == AnimationStatus.dismissed) {
//如果动画已经消失,则开始动画
_controller.forward();
}
setState(() {
_state = state;
});
});
//启动动画
_controller.forward();
}
}
源代码
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//尝试扩展或实现num时,除int或double之外的任何类型都是编译时错误
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
double _animationValue;
AnimationStatus _state;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve)
..addListener(() {
setState(() {
_animationValue = _animation.value;
});
})
..addStatusListener((AnimationStatus state) {
if (state == AnimationStatus.completed) {
_controller.reverse();
} else if (state == AnimationStatus.dismissed) {
_controller.forward();
}
setState(() {
_state = state;
});
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day10"),
),
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: <Widget>[
AnimatorTransition(
child: FlutterLogo(
style: FlutterLogoStyle.horizontal,
),
animation: _animation,
),
Text("动画值:" + _animationValue.toString()),
Text("动画状态:" + _state.toString()),
],
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
child: this.child,
animation: animation,
builder: (BuildContext context, Widget child) {
return Container(
height: animation.value,
width: animation.value,
child: child,
);
},
),
);
}
}
1、简介
DecoratedBoxTransition
表示一个边框动画,可以通过控制器去控制动画边框值的改变,从而控制动画边框2、构造函数
DecoratedBoxTransition({
Key key,
this.decoration,
this.position,
this.child,
})
Animation
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<Decoration> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: DecoratedBoxTransition(
position: DecorationPosition.background,
decoration: animation,
child: Container(
child: this.child,
),
),
);
}
}
1、简介
FadeTransition
表示一个透明度动画,可以通过控制器去控制动画透明度值的改变,从而控制动画的透明度2、构造函数
FadeTransition({
Key key,
this.opacity,
this.alwaysIncludeSemantics,
Widget child,
})
Animation
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: FadeTransition(
//是否包含子语义而不管不透明度
alwaysIncludeSemantics: false,
opacity: animation,
child: this.child,
),
);
}
}
1、简介
PositionedTransition
表示一个矩形位置的动画,可以通过控制器去控制动画矩形值的改变,从而控制动画的矩形位置2、构造函数
PositionedTransition({
Key key,
this.rect,
Widget child,
})
Animation
3、例子
这里需要注意的是PositionedTransition的父控件必须是Stack
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<RelativeRect> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
//绝对定位的动画实现, 需要Stack包裹
return Stack(
children: <Widget>[
PositionedTransition(
rect: animation,
child: this.child,
),
],
);
}
}
1、简介
RotationTransition
表示一个旋转动画,可以通过控制器去控制动画旋转值的改变,从而控制动画的旋转2、构造函数
RotationTransition({
Key key,
this.turns,
this.alignment,
Widget child,
})
Animation
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: RotationTransition(
//旋转的锚定坐标
alignment: Alignment.center,
turns: animation,
child: this.child,
),
);
}
}
1、简介
ScaleTransition
表示一个缩放动画,可以通过控制器去控制动画缩放值的改变,从而控制动画的缩放2、构造函数
ScaleTransition({
Key key,
this.scale,
this.alignment,
Widget child,
})
Animation
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: ScaleTransition(
//缩放的锚定坐标
alignment: Alignment.topLeft,
scale: animation,
child: this.child,
),
);
}
}
1、简介
SizeTransition
表示一个尺寸动画,可以通过控制器去控制动画尺寸值的改变,从而控制动画的尺寸2、构造函数
SizeTransition({
Key key,
this.sizeFactor,
this.axis,
this.axisAlignment,
Widget child,
})
Animation
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
final Axis axis;
AnimatorTransition({this.child, this.animation, this.axis = Axis.vertical});
@override
Widget build(BuildContext context) {
return Center(
child: SizeTransition(
axisAlignment: 2.0,
axis: axis,
sizeFactor: animation,
child: this.child,
),
);
}
}
1、简介
SlideTransition
表示一个平移动画,可以通过控制器去控制动画尺寸值的改变,从而控制动画的平移位置2、构造函数
SlideTransition({
Key key,
this.position,
this.transformHitTests,
this.textDirection,
Widget child,
})
Animation
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<Offset> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: SlideTransition(
transformHitTests: true,
textDirection: TextDirection.rtl,
position: animation,
child: this.child,
),
);
}
}