react-navigation转场动画效果(跨页跳转和跨页回跳)

在react-native开发过程中,往往会遇到产品的各种关于转场动画的需求,比如登录页需要从地步modal上来,又或者有这种需求,push的页面是A->B->C->D,然后他要求pop回去的路线是
D->B->A,这就是跨页回跳,或者还有这种需求,push的页面是A->B->D,然后pop的路线是
D->C->B->A,C页面在push过程中并不存在。

1.modal效果

react-navigation的StackNavigator下的属性mode 可以设置转场效果,但是这边一设置,就是这个导航下所有页面的效果都是这个,也就是要么全是push,要么全是modal,这确实比较坑,不知道最新版的有没有其他解决方案。

最终我找到了transitionConfig这个属性,这个属性可以自定义转场动画,我在navigate方法中传递一个参数为isModal的参数,默认为false,当需要modal的时候

this.props.navigation.navigate('XXX',{isModal:true})

然后在router那设置transitionConfig

const TransitionConfiguration = () => (

  {

    containerStyle:{},
    screenInterpolator: (sceneProps) => {
      global.sceneProps = sceneProps
      const { scene } = sceneProps;
      const { route } = scene;
      const params = route.params || {};
      const isModal = params.isModal;
      if (isModal){
        //当为`true`时,采用`modal`效果
        return CardStackStyleInterpolator.forVertical(sceneProps);
      }else {
        return CardStackStyleInterpolator.forHorizontal(sceneProps);
      }
    },

2.跨页回跳

push:A->B->C->D pop:D->B->A

起初我们找到了goback()方法可以传key,所以采用了在需要回跳的页面设置key,然后在之后的页面回跳回来直接使用goback(key),这样就能回到设置key的页面。

上面是一种思路,这是由上一个的页面控制下一个页面是否需要保持key,是否需要之后的页面直接回跳到这里,前两天又看了遍react-navigation的api,

 pop: (n, params) =>
    navigation.dispatch(
      NavigationActions.pop({ n, immediate: params && params.immediate })
    ),

发现这个api可以传n,经过尝试是可以直接传n,控制回跳页面数量,当传超过栈的数量时,直接回道栈底。但是这是由后级页面决定回跳几个页面的,逻辑判断要写在触发回跳的页面。

3.跨页跳转

push:A->B->D pop:D->C->B->A

解决方案
我仔细看了react-navigation的底层文件,发现了他transitionConfig属性可以配置转场动画,CardStackStyleInterpolator对象下默认有5种动画

export default {
  forHorizontal, //水平,正常push,从右往左
  forVertical,   //modal模式,从下到上
  forFadeFromBottomAndroid,  //安卓的效果
  forFade,  //fade模式
  canUseNativeDriver, //闪一下
};

然后我加了一种模式forHorizontalBack,效果类似back返回,实际上是push,新增了一个方法

function  forHorizontalBack(props) {
  
  const { layout, position, scene } = props;
  
  if (!layout.isMeasured) {
    return forInitial(props);
  }
  const interpolate = getSceneIndicesForInterpolationInputRange(props);



  if (!interpolate) return { opacity: 0 };

  const { first, last } = interpolate;
  const index = scene.index;
  const opacity = position.interpolate({
    inputRange: [first, first + 0.01, index, last - 0.01, last],
    outputRange: [0, 1, 1, 0.85, 0],
  });

  const width = layout.initWidth;
  const { scenes } = props;
  const lastSceneIndexInScenes = scenes.length - 1;
  const isBack = !scenes[lastSceneIndexInScenes].isActive;

  var translateX

  if (isBack){
  //改了动画后造成back的时候pop动画变成了push效果,所以在这边判断,系数用之前的,效果为pop效果
   translateX = position.interpolate({
      inputRange: [first, index, last],
      outputRange: I18nManager.isRTL
        ? [-width, 0, width * 0.3]
        : [width, 0, width * -0.3],
    });

  }else {

    translateX = position.interpolate({
      inputRange: [first, index, last],
      outputRange: I18nManager.isRTL
        ? [-width, 0, width * 0.3]
        : [width * -0.7, 0, width],//修改了这个系数,效果是本来push从右往左变成从左往右
    });
  }


  const translateY = 0;

  return {
    opacity,
    transform: [{ translateX }, { translateY }],
  };

}

然后在router那设置transitionConfig

const TransitionConfiguration = () => (

  {

    containerStyle:{},
    screenInterpolator: (sceneProps) => {
      global.sceneProps = sceneProps
      const { scene } = sceneProps;
      const { route } = scene;
      const params = route.params || {};
      const isModal = params.isModal;

      const isSpan = params.span;
      if(isSpan){

        return CardStackStyleInterpolator.forHorizontalBack(sceneProps);
      }

      if (isModal){

        return CardStackStyleInterpolator.forVertical(sceneProps);
      }else {

        return CardStackStyleInterpolator.forHorizontal(sceneProps);
      }


    },


  })

因为本人原来是做iOS的,项目需要才开始摸索react-native,开发时间也不长,上面的总结如有不正确或者更好的方案,希望大神们多多指教。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容