浅析react-native的Navigator组件03之动画切换

前言:【初级内容】传数据搞定了,接下来是这个动画切换了。前面传数据,因为理论上对象里面啥都能装,所以只需要能传个对象就行了。关于动画切换就没有那么好的事情了,大家的需求会更加多样化。比如希望每个页面都换一种切换方式,比如希望能修改默认的动画,更高级的想自己定制动画等。有需求就实现,当然也只能简单实现……

默认动画介绍

在初始化语句中,那句

1
2
3
4
5
configureScene={
(route)=> {
return Navigator.SceneConfigs.VerticalDownSwipeJump;
}
}

就是用来指定切换动画的,默认动画都写在Navigator.SceneConfigs这个对象里面。目前默认动画有如下几种:

1
2
3
4
5
6
7
8
9
PushFromRight //push时候新页面从右边滑进来,pop时当前页往右边滑走。支持ios的屏幕左边缘往右滑的返回(调用pop,以下简称边缘返回),但不知道安卓是啥情况。
FloatFromRight //和PushFromRight 是一样的(至少0.17版的源代码是一样的,不知道之后的版本改没改)
FloatFromLeft //和FloatFromRight 方向是反过来的,支持边缘返回。
FloatFromBottom //push时新页面从下往上滑,pop就反过来。支持手势的下拉返回(调用pop方法)
FloatFromBottomAndroid //动画方向和FloatFromBottom是一样的,但动画效果很细微,只能看到很短的滑动就切换了。不支持手势。
FadeAndroid //渐隐式切换,不支持手势。
HorizontalSwipeJump //push时候新页面从右边滑进来,pop时当前页往右边滑走,支持手势左右滑动切换(但需要你进入过新页面,就是route栈里面已经有内容,因为手势触发的是jumpFoward和jumpback的方法)
VerticalUpSwipeJump //push的时候新页面从下往上滑进来,pop时当前页从上往下滑走。支持手势从左往右滑返回(jumpBack)。
VerticalDownSwipeJump ////push的时候新页面从上往下滑进来,pop时当前页从下往上滑走。支持手势从左往右滑返回(jumpBack)。

切换时指定动画

demo1: 链接 (基于0.17,ios,跳第二页和第三页分别用了不同的动画)
demo2: 链接 (遍历出SceneConfigs里面所有的切换动画跳转第二页)
这个需求实现起来很简单,就是利用之前那个传递属性的功能,把SceneConfigs的动画名称传给configureScene就行了。比如我把这个动画属性取名为scene。初始化代码修改成这样:

1
2
3
4
5
6
7
configureScene={
(route)=> {
return route.scene || Navigator.SceneConfigs.FadeAndroid;
}
}

//加了个route.scene,如果我们没有传递route.scene的值,就使用后面这个FadeAndroid作为默认切换动画。

其他页面想要临时指定切换动画时,修改push代码如下:

1
2
3
4
5
navigator.push({
component:Secondpage,
scene: Navigator.SceneConfigs.FloatFromLeft,
})
//这样push页面的时候会使用FloatFromLeft的动画进行切换。记得当前页面需要导入Navigator组件。

修改默认动画

对于切换动画的自定义的需求,我估计应该有不少。自己写的测试demo倒是无所谓,但如果是商业产品,丢出来给大家用的,要求(或称逼格)高一点的,大都会让你改。怎么改呢?
最直接的方法,就是修改NavigatorSceneConfigs.js这个文件,它放在你的项目文件的node_modules/react-native/Libraries/CustomComponents/Navigator/的目录下面,里面就是这个切换动画的整个实现源代码(注,Navigator的实现代码也在里面,有兴趣的可以看看),理论上来说你看哪个不顺眼直接改就是了,我先来试试。
代码里面大概分了几个部分,最前面是定义animation动画的一些方法,然后是关于手势(Gesture)的一些方法,最后才是NavigatorSceneConfigs这个对象的完成,对象每个key的值就是把动画和手势结合在一起,凑成一个具体切换动画的对象。前面动画和手势的代码目前还搞不太懂,只能改改这个结合部分。具体切换动画对象的示例代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FloatFromBottom: {
...BaseConfig, // 先继承一个基础切换动画的设定
gestures: { // 覆盖基础设定里面的手势部分
pop: { //这个表示调用pop方法时候的手势是是怎样的
...BaseLeftToRightGesture,
edgeHitWidth: 150,
direction: 'top-to-bottom',
fullDistance: SCREEN_HEIGHT,
}
},
animationInterpolators: { //这个表示页面切入(push)和页面切出(一般是pop)时的动画应该是什么样子
into: buildStyleInterpolator(FromTheFront), //切入时调用哪段动画
out: buildStyleInterpolator(ToTheBack), //切出时调用哪段动画
},

当然,里面的那些参数也不能乱改,比如切入的动画,在默认的实现里面,你基本上就只能用FromXXXX系列,而切出去的时候只能用ToThexxx或者xxToTheXXX。比如我们想把前面哪个FloateFromRight的特效换一下:

1
2
3
4
5
6
7
8
FloatFromRight: {
...BaseConfig,
animationInterpolators: {
into: buildStyleInterpolator(FadeIn),
out: buildStyleInterpolator(ToTheLeft),
},
// We will want to customize this soon
},

再试试是不是就和默认的不一样了,如果这里需要再扯清楚点,就必须要扯到animation和guesture这两个可能比Navigator更复杂的玩意儿了,一两篇都写不完那种。所以这次就到此为止吧,有兴趣的可以自己去看源代码。

这里代码里面又出现了神奇的三个点,它还是ES7那个展开对象的功能,就说把BaseConfig的给展开,同时,如果后面有重名的Key,后面的会把BaseConfig里面的内容给覆盖掉,就刚好可以让我们拿来做修改功能的需求。