Flutter动画widget合集2
你可以在我的博客看到我的文章 包含的比较多,但是都比较零散,有以下几个部分。
AnimatedCrossFade
AnimatedOpacity
AnimatedPadding
AnimatedSize
AnimatedAlign
AnimatedSwitcher
AnimatedPositioned
AnimatedIcon
AnimatedCrossFade
这个控件的效果是在两个控件切换时进行显示上的过渡。 控件内需要有两个widget,一个firstChild,一个secondChild,通过crossFadeState控制显示哪个child,并在切换时进行渐隐渐显的效果。
void _animating() {
setState(() {
//状态切换
status = !status;
});
}
GestureDetector(
onTap: _animating,
child: Center(
child: AnimatedCrossFade(
firstChild: Container(
width: 200,
height: 200,
child: Text(
"第一个子widget",
style: TextStyle(
backgroundColor: Colors.deepOrange, fontSize: 30),
),
),
secondChild: Text(
"第二个子widget",
style: TextStyle(
backgroundColor: Colors.blueAccent, fontSize: 30),
),
//用于控制显示哪个widget
crossFadeState: status
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: Duration(milliseconds: 500),
),
),
),
两个childWidget在切换时的过渡效果,那些辅助线是我开启了Debug paint才显示的,可以忽略掉。
AnimatedOpacity
控件透明度动画, 在opacity的值发生改后自动对childWidget进行透明度动画。
void _animating() {
setState(() {
//状态切换
status = !status;
});
}
GestureDetector(
onTap: _animating,
child: Center(
child: AnimatedOpacity(
child: Container(
width: 200,
height: 200,
color: Colors.deepOrange,
child: Text(
"透明度动画演示",
style: TextStyle(fontSize: 40.0),
),
),
//在opacity的值发生改后自动进行透明度动画
opacity: status ? 1.0 : 0.0,
duration: Duration(milliseconds: 500)),
),
),
AnimatedOpacity内childWidget的透明度发生了改变
AnimatedPadding
可以改变子控件的padding的动画,和对AnimateContainer的padding修改时的动画效果一样
void _animating() {
setState(() {
//状态切换
status = !status;
});
}
GestureDetector(
onTap: _animating,
child: Center(
child: Container(
//外部我用了紫色背景
color: Colors.deepPurpleAccent,
child: AnimatedPadding(
//改变的是Text的padding
child: Text(
"padding动画演示",
style: TextStyle(fontSize: 40.0),
),
duration: Duration(milliseconds: 500),
padding: EdgeInsets.all(status ? 50 : 0.0),
),
),
),
),
可以看到因为padding的改变,外层的Container被撑大了
AnimatedSize
这个控件的用意是,当子控件的大小发生变化时会有一个动画。不过目前(2019.7.25)这个控件显示的是有问题的。
如果你想使用的话,推荐Animatecontainer的方式进行控件大小的改变
GestureDetector(
onTap: _animating,
child: AnimatedSize(
child: Container(
color: Colors.deepPurpleAccent,
//对高度进行了演示。
height: status ? 60 : 150,
child: Text(
"AnimatedSize动画演示",
style: TextStyle(fontSize: 40.0),
),
),
duration: Duration(milliseconds: 500),
//注意这个,要在state里width TickerProviderStateMixin
vsync: this,
),
),
可以看到,变大时候时候是有动画的,但是变小的时候,没有期望中的动画。更多信息可以在issue中看到。 github.com/flutter/flu…
AnimatedAlign
对控件的对齐方式进行动画
GestureDetector(
onTap: _animating,
child: AnimatedAlign(
//中心对齐和中心靠右对齐
alignment: status ? Alignment.center : Alignment.centerRight,
duration: Duration(milliseconds: 500),
child: Container(
color: Colors.deepPurpleAccent,
child: Text(
"AnimatedAlign动画演示",
style: TextStyle(fontSize: 40.0),
),
),
),
),
AnimatedSwitcher
void _animating() {
setState(() {
switchSize++;
status = !status;
});
}
GestureDetector(
onTap: _animating,
child: AnimatedSwitcher(
//进行自定义的切换动画
transitionBuilder: (Widget child, Animation<double> animation) {
return ScaleTransition(child: child, scale: animation);
},
//如果childWidget的key发生的变动,就会触发动画,这里是Text和Container的切换,二者的key自然是不同的,如果同时Text,则要注意给Text设置不同的key
child: status
? Text(
"AnimatedSwitcher动画演示${switchSize}",
style: TextStyle(fontSize: 40.0),
)
: Container(
width: 50,
height: 50,
color: Colors.deepOrange,
),
duration: Duration(milliseconds: 500),
),
)
这个是在Text和Container切换的动画,也即上面代码的效果
这个是在不同的Text直接切换的动画,注意我设置了不同的Text的值。
AnimatedPositioned
可以对控件的位置进行动画。但是有一些限制。
- 父Widget必须是Stack
- 在水平维度上有left,right,width,这三者必须有一个值为null
- 在垂直维度上有top,bottom,height,这三者必须有一个值为null
同样的这个动画也可以用AnimateContainer来实现。
GestureDetector(
onTap: _animating,
child: Stack(
children: <Widget>[
AnimatedPositioned(
top: status ? 50 : 100,
height: status ? 50 : 100,
left: status ? 50 : 100,
child: Container(
color: Colors.deepPurpleAccent,
child: Text(
"AnimatedPositioned动画演示${switchSize}",
style: TextStyle(fontSize: 30.0),
),
),
duration: Duration(milliseconds: 500),
),
],
),
),
AnimatedIcon
AnimatedIcon,动画图标
@override
void initState() {
super.initState();
_controller =
//同样要使所在的State with TickerProviderStateMixin
AnimationController(vsync: this, duration: Duration(milliseconds: 500));
}
void _animating() {
setState(() {
if (status) {
_controller.forward();
} else {
_controller.reverse();
}
status = !status;
});
}
GestureDetector(
onTap: _animating,
child: Wrap(
children: <Widget>[
AnimatedIcon(
size: 100,
icon: AnimatedIcons.arrow_menu,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.menu_arrow,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.close_menu,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.menu_close,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.home_menu,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.menu_home,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.list_view,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.view_list,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.ellipsis_search,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.search_ellipsis,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.add_event,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.event_add,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.pause_play,
progress: _controller,
),
AnimatedIcon(
size: 100,
icon: AnimatedIcons.play_pause,
progress: _controller,
),
],
),
),
这里我把,所有官方的AnimatedIcon列出来的,这个实际上还是Path实现的。