react-navigation轉(zhuǎn)場(chǎng)動(dòng)畫效果(跨頁(yè)跳轉(zhuǎn)和跨頁(yè)回跳)

在react-native開(kāi)發(fā)過(guò)程中,往往會(huì)遇到產(chǎn)品的各種關(guān)于轉(zhuǎn)場(chǎng)動(dòng)畫的需求,比如登錄頁(yè)需要從地步modal上來(lái),又或者有這種需求,push的頁(yè)面是A->B->C->D,然后他要求pop回去的路線是
D->B->A,這就是跨頁(yè)回跳,或者還有這種需求,push的頁(yè)面是A->B->D,然后pop的路線是
D->C->B->A,C頁(yè)面在push過(guò)程中并不存在。

1.modal效果

react-navigation的StackNavigator下的屬性mode 可以設(shè)置轉(zhuǎn)場(chǎng)效果,但是這邊一設(shè)置,就是這個(gè)導(dǎo)航下所有頁(yè)面的效果都是這個(gè),也就是要么全是push,要么全是modal,這確實(shí)比較坑,不知道最新版的有沒(méi)有其他解決方案。

最終我找到了transitionConfig這個(gè)屬性,這個(gè)屬性可以自定義轉(zhuǎn)場(chǎng)動(dòng)畫,我在navigate方法中傳遞一個(gè)參數(shù)為isModal的參數(shù),默認(rèn)為false,當(dāng)需要modal的時(shí)候

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

然后在router那設(shè)置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){
        //當(dāng)為`true`時(shí),采用`modal`效果
        return CardStackStyleInterpolator.forVertical(sceneProps);
      }else {
        return CardStackStyleInterpolator.forHorizontal(sceneProps);
      }
    },

2.跨頁(yè)回跳

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

起初我們找到了goback()方法可以傳key,所以采用了在需要回跳的頁(yè)面設(shè)置key,然后在之后的頁(yè)面回跳回來(lái)直接使用goback(key),這樣就能回到設(shè)置key的頁(yè)面。

上面是一種思路,這是由上一個(gè)的頁(yè)面控制下一個(gè)頁(yè)面是否需要保持key,是否需要之后的頁(yè)面直接回跳到這里,前兩天又看了遍react-navigation的api,

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

發(fā)現(xiàn)這個(gè)api可以傳n,經(jīng)過(guò)嘗試是可以直接傳n,控制回跳頁(yè)面數(shù)量,當(dāng)傳超過(guò)棧的數(shù)量時(shí),直接回道棧底。但是這是由后級(jí)頁(yè)面決定回跳幾個(gè)頁(yè)面的,邏輯判斷要寫在觸發(fā)回跳的頁(yè)面。

3.跨頁(yè)跳轉(zhuǎn)

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

解決方案
我仔細(xì)看了react-navigation的底層文件,發(fā)現(xiàn)了他transitionConfig屬性可以配置轉(zhuǎn)場(chǎng)動(dòng)畫,CardStackStyleInterpolator對(duì)象下默認(rèn)有5種動(dòng)畫

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

然后我加了一種模式forHorizontalBack,效果類似back返回,實(shí)際上是push,新增了一個(gè)方法

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){
  //改了動(dòng)畫后造成back的時(shí)候pop動(dòng)畫變成了push效果,所以在這邊判斷,系數(shù)用之前的,效果為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],//修改了這個(gè)系數(shù),效果是本來(lái)push從右往左變成從左往右
    });
  }


  const translateY = 0;

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

}

然后在router那設(shè)置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);
      }


    },


  })

因?yàn)楸救嗽瓉?lái)是做iOS的,項(xiàng)目需要才開(kāi)始摸索react-native,開(kāi)發(fā)時(shí)間也不長(zhǎng),上面的總結(jié)如有不正確或者更好的方案,希望大神們多多指教。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AGI閱讀 16,003評(píng)論 3 119
  • 前言的前言 唐巧前輩在微信公眾號(hào)「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各項(xiàng)指標(biāo)...
    VincentHK閱讀 5,418評(píng)論 3 44
  • 最近,夫君迷上了《楚喬傳》,每天起床都能聽(tīng)到“跟著楚喬走,不會(huì)坑隊(duì)友”。夫君和我都是程序員,每天早上十點(diǎn)出門,晚上...
    插著扇子的石頭閱讀 480評(píng)論 14 15
  • 百詞斬是一個(gè)幫助用戶記憶單詞的APP。 交互方面比較特別。進(jìn)入APP后是橫屏的展現(xiàn)方式。但是其中一些功能會(huì)轉(zhuǎn)為豎屏...
    貴將閱讀 773評(píng)論 0 0