1.前言
LayoutAnimation——布局动画,当布局变化时,会自动将组件运动到新的位置上。相较于RequestAnimationFrame,LayoutAnimation可以更方便的实现出“弹性动画”,“缓入缓出”等效果。
使用LayoutAnimation的常用方法是调用LayoutAnimation.configureNext
方法,然后使用setState设置组件的状态。
2.LayoutAnimation方法与属性
LayoutAnimation的方法
static configureNext(config: Config, onAnimationDidEnd?: Function)
配置下一次布局要发生的动画。
- @param config 表示动画相应的属性
- duration 动画持续时间,单位是毫秒
- create, 组件创建时的动画。
- update, 组件更新时的动画。
- delete, 组件销毁时的动画。
- @param onAnimationDidEnd 当动画结束的时候被调用。只在iOS设备上支持。
- @param onError 当动画产生错误的时候被调用。只在iOS设备上支持。
config的示例如下:
{
duration: 700, //持续时间
create: { // 创建
type: LayoutAnimation.Types.linear,
property: LayoutAnimation.Properties.scaleXY // opacity、scaleXY
},
update: { // 更新
type: LayoutAnimation.Types.spring,
springDamping: 0.4
},
}
create、update和delete的动画类型Anim
定义如下:
type Anim = {
duration?: number, //动画时长
delay?: number, //时间延迟,单位:毫秒
springDamping?: number, //弹跳动画阻尼系数,配合spring使用
initialVelocity?: number, //初始速度
type?: $Enum<typeof TypesEnum>, //动画类型
property?: $Enum<typeof PropertiesEnum>, //动画属性
}
其中type定义在LayoutAnimation.Types
中:
- spring:弹跳
- linear:线性
- easeInEaseOut:缓入缓出
- easeIn:缓入
- easeOut:缓出
property定义在LayoutAnimation.Properties
中:
- opacity:透明度
- scaleXY:缩放
static create(duration: number, type, creationProp)
用来创建configureNext所需的config参数的辅助函数。
- @param duration:动画持续时间。
- @param type:create和update时的动画类型,定义在
LayoutAnimation.Types
中。 - @param creationProp:create时的动画属性,定义在
LayoutAnimation.Properties
中。
LayoutAnimation的属性
- Types:动画类型
- Properties:属性(主要涉及:opacity,scaleXY)
- configChecker:配置检查器
- Presets:动画效果默认配置项
- easeInEaseOut 缓入缓出动画类型
- linear 线性动画类型
- spring 弹性动画类型
3.LayoutAnimation使用实例
还是基于上一节RequestAnimationFrame的实例,修改其中的_onPress方法,
_onPress() {
LayoutAnimation.configureNext({
duration: 700,
create: {
type: LayoutAnimation.Types.spring,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: LayoutAnimation.Types.spring,
},
});
this.setState({width: this.state.width + 10, height: this.state.height + 10});
}
要注意的是,安卓平台使用 LayoutAnimation 动画必须加上一下代码,否则动画会失效:
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
}
效果如下:
这里还可以利用create方法简化上述代码:
_onPress() {
LayoutAnimation.configureNext(LayoutAnimation.create(700,
LayoutAnimation.Types.spring,
LayoutAnimation.Properties.scaleXY));
this.setState({width: this.state.width + 10, height: this.state.height + 10});
}
其实现效果与上面代码相同。如果要实现缓入缓出或者线性效果,将LayoutAnimation.Types.spring
替换成LayoutAnimation.Types.linear
或LayoutAnimation.Types.easeInEaseOut
即可。
另外通常将LayoutAnimation动画在componentWillUpdate()方法里指定,不需要在点击事件里指定。
componentWillUpdate() {
LayoutAnimation.configureNext({
duration: 700,
create: {
type: LayoutAnimation.Types.spring,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: LayoutAnimation.Types.spring,
},
});
}
而点击事件中只处理state值的修改
_onPress() {
this.setState({ width: this.state.width + 20, height: this.state.height + 20 });
}
完整Demo示例: git源码地址
4.小结
通过前面对LayoutAnimation介绍及体验,可以看出用LayoutAnimation实现的动画效果很流畅,动画过程柔和,没有生硬的感觉。此外可以灵活配置动画参数,基本能满足单个动画的需求。不过LayoutAnimation也有其局限的地方,如何要实现组合动画,例如先放大,在平移,实现起来就比较困难了。这里需要监听上一个动画的结束事件,再开始下一个动画的执行。在configureNext的第二个参数是可以监听动画结束的,但是只在iOS平台有效。那么如何实现更灵活丰富的动画效果呢?幸运的是React Native为我们提供了功能强大的高级动画api——Animated。下一篇文章将介绍Animated的使用。