平时我们在切换 Widget 的时候是怎样的?
有没有动画效果?是不是直接改变了一个 Widget?
类似于这样的:
如果是的话,那么今天所说的 Widget,绝对符合你的口味。
那如何在 Flutter 当中切换 Widget 的时候加上特效?完成这样的效果?
AnimatedSwitcher
了解一下。
话不多说,功能我们已经了解,再来看一下官方的介绍:
A widget that by default does a FadeTransition[1] between a new widget and the widget previously set on the AnimatedSwitcher[2] as a child. If they are swapped fast enough (i.e. before duration[3] elapses), more than one previous child can exist and be transitioning out while the newest one is transitioning in. If the "new" child is the same widget type and key as the "old" child, but with different parameters, then AnimatedSwitcher[4] will not do a transition between them, since as far as the framework is concerned, they are the same widget and the existing widget can be updated with the new parameters. To force the transition to occur, set a Key[5] on each child widget that you wish to be considered unique (typically a ValueKey[6] on the widget data that distinguishes this child from the others). 大致意思就是: 默认情况下是执行透明度的动画。 如果交换速度足够快,则存在多个子级,但是在新子级传入的时候将它移除。 如果新 Widget 和 旧 Widget 的类型和键相同,但是参数不同,那么也不会进行转换。如果想要进行转换,那么要添加一个 Key。
再来看构造函数,来确定如何使用:
const AnimatedSwitcher({
Key key,
this.child,
@required this.duration,
this.reverseDuration,
this.switchInCurve = Curves.linear,
this.switchOutCurve = Curves.linear,
this.transitionBuilder = AnimatedSwitcher.defaultTransitionBuilder,
this.layoutBuilder = AnimatedSwitcher.defaultLayoutBuilder,
}) : assert(duration != null),
assert(switchInCurve != null),
assert(switchOutCurve != null),
assert(transitionBuilder != null),
assert(layoutBuilder != null),
super(key: key);
来解释一下每个参数:
1.child:不用多说2.duration:动画持续时间3.reverseDuration:从新的 Widget 到旧的 Widget 动画持续时间,如果不设置则为 duration 的值4.switchInCurve:动画效果5.switchOutCurve:同上6.transitionBuilder:设置一个新的转换动画7.layoutBuilder:包装新旧 Widget 的组件,默认是一个 Stack
其中必要参数就是一个 duration
,那既然知道如何使用了,那就开撸。
前面我们看的图,就是在对 AppBar
上的 actions
进行操作,
其实这个例子在实际开发当中经常存在,肯定要删除一些东西的嘛,然后选中了以后批量删除。
那这里也不多说,直接上代码,然后解释:
class _AnimatedSwitcherPageState extends State<AnimatedSwitcherPage> {
IconData _actionIcon = Icons.delete;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AnimatedSwitcherPage'),
actions: <Widget>[
AnimatedSwitcher(
transitionBuilder: (child, anim){
return ScaleTransition(child: child,scale: anim);
},
duration: Duration(milliseconds: 300),
child: IconButton(
key: ValueKey(_actionIcon),
icon: Icon(_actionIcon),
onPressed: () {
setState(() {
if (_actionIcon == Icons.delete)
_actionIcon = Icons.done;
else
_actionIcon = Icons.delete;
});
}),
)
],
),
body: Container());
}
}
我们定义的是一个 StatefulWidget
,因为在切换 Widget 的时候要调用 setState()
,
下面来说一下整个流程:
1.首先定义好我们初始化的 Icon的数据为 Icons.delete
2.在 AppBar
的 actions
里面加入 AnimatedSwitcher
3.设置 transitionBuilder
为 缩放动画 ScaleTransition
4.给 AnimatedSwitcher
的 child 为 IconButton
5.因为前面官方文档说过,如果 Widget 类型一样,只是数据不一样,那么想要动画,就必须添加 Key。6.所以我们给 IconButton
添加了一个 ValueKey
,值就为定义好的 IconData
7.最后在点击事件中切换两个 Icon 就完成了
最后再看一下效果:
使用该控件最应该注意的点就是 Key 的问题,一定要记住:
如果新 Widget 和 旧 Widget 的类型和键相同,但是参数不同,那么也不会进行转换。如果想要进行转换,那么要添加一个 Key。
完整代码已经传至GitHub:https://github.com/wanglu1209/WFlutterDemo
[1]
FadeTransition: https://api.flutter.dev/flutter/widgets/FadeTransition-class.html
[2]
AnimatedSwitcher: https://api.flutter.dev/flutter/widgets/AnimatedSwitcher-class.html
[3]
duration: https://api.flutter.dev/flutter/widgets/AnimatedSwitcher/duration.html
[4]
AnimatedSwitcher: https://api.flutter.dev/flutter/widgets/AnimatedSwitcher-class.html
[5]
Key: https://api.flutter.dev/flutter/foundation/Key-class.html
[6]
ValueKey: https://api.flutter.dev/flutter/foundation/ValueKey-class.html