react-navigation使用技巧(進階篇)

之前寫過react-navigation使用技巧,那篇文章中主要講了react-navigation的屬性铭污,封裝和一些小技巧恋日。雖然上篇文章中也有一些小技巧,但因為補充的比較晚嘹狞,導致有些人沒有看全岂膳,再加上我又找到了一些新的小玩意,特此寫了本篇文章磅网,如果之后還有新發(fā)現(xiàn)谈截,也會再這篇文章中更新出來。

如果遇到什么問題可以在評論區(qū)回復涧偷,或者加QQ群397885169詢問

1簸喂、讓TabBar擁有點擊事件

react-navigationbeta13版本之后,已經默認支持點擊事件了嫂丙,它被放在了TabNavigator中娘赴,屬性名為tabBarOnPress,內部提供了兩個屬性跟啤,一個方法({ route, index } , jumpToIndex)诽表,使用方法如下:

tabBarOnPress:(obj)=>{
            console.log(obj);

            obj.jumpToIndex(obj.scene.index)
        },

最新幾個版本的react-navigation中唉锌,將代碼和文件路徑修改了,所以之前的方式失效了竿奏,在這里提供一個新的方法來修改Tabbar的點擊事件袄简。
#### 原文鏈接

一共要修改添加大大小小12處地方哦!涉及4個js文件泛啸。 這個修改已經被作者提交到react-navigation中了绿语,希望在以后的更新中可以看到這次更新。

使用方法

static navigationOptions = ({navigation,screenProps}) => ({
    headerTitle:'首頁',
    tabBarOnPress: (scene,jumpToIndex) => {
         console.log(scene); 
         jumpToIndex(scene.index)
    },
});

~~ 注意:如果調用了tabBarOnPress方法候址,會默認關閉點擊跳轉事件吕粹,需要手動開啟。岗仑!~~

以下代碼已被廢棄

感謝群友再遇見的分享匹耕。

官方的api里面是沒有提供tabBar的點擊事件的,但在開發(fā)中經常需要監(jiān)聽tabBar的點擊事件荠雕,解決這個問題的一種方法就是去修改源碼稳其,另一種是監(jiān)聽onTransitionEnd。(第二種方法這里先不討論)

源碼中一共需要修改8處地方炸卑,包含3個js文件既鞠。源碼在下面。

1盖文、react-navigation目錄下src/views/TabView/TabBarBottom.js

TabBarBottom.png

2嘱蛋、react-navigation目錄下src/views/TabView/TabBarTop.js

TabBarTop.png

3、react-navigation目錄下src/views/TabView/TabView.js

TabView.png

#### 注意:第111行中的getScreenConfig需要手動改成getScreenOptions五续,要不然修改完源碼會報錯浑槽。

#### 源碼在這里,要注意修改getScreenOptions

修改源碼之后返帕,在頁面中這么用:

static navigationOptions = ({navigation,screenProps}) => ({
    onTabPress:(()=>{
        alert('Home');
    })
});

2、修改頁面的跳轉動畫

在上一篇文章中篙挽,說了怎么將安卓的跳轉動畫改成iOS那樣的荆萤,但其實react-navigation一共提供了4種跳轉動畫:
1、從右向左: forHorizontal铣卡;
2链韭、從下向上: forVertical
3煮落、安卓那種的從下向上: forFadeFromBottomAndroid敞峭;
4、無動畫: forInitial蝉仇。

但因為庫的限制旋讹,想實現(xiàn)某些頁面使用某種動畫還是很難的殖蚕,只能通過Demo中提供的笨方法來實現(xiàn)。

首先還是導入react-navigation中的方法


import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';

2.0
import StackViewStyleInterpolator from 'react-navigation/src/views/StackView/StackViewStyleInterpolator';

如果要改變跳轉動畫只能在StackNavigator中實現(xiàn)transitionConfig方法

const MainStack = StackNavigator({
    Main:{
        screen:Main,
    },
},{
    // mode:'modal',
    headerMode: 'screen',
    transitionConfig:()=>({
     // 只要修改最后的forVertical就可以實現(xiàn)不同的動畫了沉迹。
      screenInterpolator:CardStackStyleInterpolator.forVertical,
    })
});

3睦疫、在Reset方法中傳參

react-navigation中的reset方法,應該都不陌生吧鞭呕,重置路由蛤育。但有的需求是在登陸之后,重置路由并傳遞參數(shù)到某個頁面葫松,之前一直以為不可以瓦糕,直到群友的react-native reset方法中傳參的寫法的這篇文章出現(xiàn),感謝群友nextChampion的貢獻腋么。

const resetAction = NavigationActions.reset({
    index: 0,
    actions: [
    NavigationActions.navigate({routeName: 'Home', params: { token: '123456' }})
    ]
})

this.props.navigation.dispatch(resetAction);

在頁面中可以通過如下方法得到參數(shù)咕娄。

this.props.navigation.state.params.token 

4、goBack返回指定頁面

在上篇文章中也有這個技巧党晋,這里是總結重發(fā)谭胚。

react-navigation目錄下src/routers/StackRouter.js

if (action.type === NavigationActions.BACK) {
    let backRouteIndex = null;
    if (action.key) {

      const backRoute = state.routes.find(
        /* $FlowFixMe */
        /* 修改源碼 */
        route => route.routeName === action.key
        /* (route: *) => route.key === action.key */
      );
      /* $FlowFixMe */
      console.log('backRoute =====',backRoute);
      backRouteIndex = state.routes.indexOf(backRoute);
      console.log('backRoute =====',backRouteIndex);
    }
    if (backRouteIndex == null) {
      return StateUtils.pop(state);
    }
    if (backRouteIndex >= 0) {
      return {
        ...state,
        routes: state.routes.slice(0, backRouteIndex+1),
        index: backRouteIndex - 1 + 1,
      };
    }
  }

注意:這樣的修改源碼之后,如果項目中使用Redux未玻,并且啟用了滑動返回灾而,很會很大幾率導致app卡死,所以并不太推薦這種方式扳剿,最好使用下面的方式

5旁趟、react-navigation集成Redux

可能會有人認為這樣集成會麻煩,而且react-navigation內部實現(xiàn)也是類似Redux的高階函數(shù)庇绽。我之前也是這么認為的锡搜,直到在識兔中,使用 Redux 修改首頁圖片之后 滑動返回 會導致app卡死瞧掺。

react-navigation集成Redux之后耕餐,能獲取當前screenkey题禀,routeNmae等參數(shù)玻孟,goBack()的時候就可以直接取到key琐脏,而不用修改源碼啦蓝谨!

具體操作步驟可以在識兔雁刷,一款用來識別圖片的開源項目中查看沮峡。

如果看不懂下面的修改步驟钧唐,可以先看下之前的文章Redux "使用"教程

集成

1征候、添加addNavigationHelpers

import {
    StackNavigator,
    TabNavigator,
    addNavigationHelpers
} from 'react-navigation';

2壹蔓、首先修改識兔中的App.js的導出方式

const AppWithNavigationState = ({ dispatch, nav }) => (
    <MyApp navigation={addNavigationHelpers({ dispatch, state: nav })}/>
);

const mapStateToProps = state => ({
    nav: state.nav,
});

export default connect(mapStateToProps)(AppWithNavigationState);

3趟妥、創(chuàng)建StackReducer

// MyApp 是在App.js中導出的
import { MyApp } from '../APP';


export default function StackReducer(state , action) {
    let nextState;
    switch (action.type) {
        default:
            nextState = MyApp.router.getStateForAction(action, state);
            break;
    }
    return nextState || state;
}

4、修改rootReducer

import nav from './StackReducer';

const RootReducer = combineReducers({
    ...,
    nav,
});

export default RootReducer;

使用

1佣蓉、修改ShiTu.js

export default connect((state) => {
    ...
    const routes  = state.nav.routes;
    return {
        ...
        routes
    };
},{...})(ShiTu)

2披摄、使用

const {routes} = this.props;
// 會有意想不到的驚喜哦亲雪!
console.log(routes);

感謝群友Roc的提供的react-navigation集成redux的 腳手架 可以通過它快速實現(xiàn)集成Redux

6行疏、安卓返回鍵在react-navigation中的正常監(jiān)聽

之前使用Navigator的時候匆光,可以通過下面的方法實現(xiàn)監(jiān)聽安卓的返回鍵,但使用了react-navigation后酿联,會很迷茫终息,不知該怎么監(jiān)聽了。

解決辦法:集成Redux咯贞让!?????? 集成完Redux周崭,在跳轉之后,就能獲得路由的length喳张,可以通過length來判斷當前頁面是第幾層续镇。

Navigator的方法

componentWillMount() {
    if (Platform.OS === 'android') {
      BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid);
    }
  }
componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackAndroid.removeEventListener('hardwareBackPress', this.onBackAndroid);
    }
  }
onBackAndroid = () => {
    const nav = this.navigator;
    const routers = nav.getCurrentRoutes();
    if (routers.length > 1) {
      nav.pop();
      return true;
    }
    return false;
  };
  ……
}

react-navigation的方式

componentWillMount() {
    if (Platform.OS === 'android') {
        BackHandler.addEventListener('handwareBackPress',this.onBackAndroid)
    }
  }
componentWillUnmount() {
    if (Platform.OS === 'android') {
        BackHandler.addEventListener('handwareBackPress',this.onBackAndroid)
    }
  }
onBackAndroid = () => {
    const routers = nav.getCurrentRoutes();
    if (routers.length > 1) {
      return true;
    }
    return false;
  };
  ……
}

// 在跳轉之后的頁面中
onBackAndroid = ()=> {

    const {routes} = this.props;
    console.log(routes);
    // alert(routes)
    if (routes.length > 1) {
        // 因為其他頁面獲得不到this.props,所以只能每個頁面都寫這個方法销部。
        this.props.navigation.goBack();
        return true;
    }
}

7摸航、快速點擊重復跳轉的解決辦法

感謝群友編程大叔的貢獻

react-navigation目錄下src/addNavigationHelpers.js

可以點擊這里查看原文鏈接

 export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) {
  // 添加點擊判斷
  let debounce = true;
  return {
      ...navigation,
      goBack: (key?: ?string): boolean =>
          navigation.dispatch(
              NavigationActions.back({
                  key: key === undefined ? navigation.state.key : key,
              }),
          ),
      navigate: (routeName: string,
                 params?: NavigationParams,
                 action?: NavigationAction,): boolean => {
          if (debounce) {
              debounce = false;
              navigation.dispatch(
                  NavigationActions.navigate({
                      routeName,
                      params,
                      action,
                  }),
              );
              setTimeout(
                  () => {
                      debounce = true;
                  },
              500,
              );
              return true;
          }
          return false;
      },
    /**
     * For updating current route params. For example the nav bar title and
     * buttons are based on the route params.
     * This means `setParams` can be used to update nav bar for example.
     */
    setParams: (params: NavigationParams): boolean =>
      navigation.dispatch(
        NavigationActions.setParams({
          params,
          key: navigation.state.key,
        }),
      ),
  };
}

8、安卓上舅桩,使用TextInput的時候會讓TabBar頂起來的解決辦法

最簡單的解決辦法就是在android目錄中酱虎,添加一句話

目錄:android/app/src/main/AndroidManifest.xml中,添加

 android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"

ps:在iOS下如果想一勞永逸的解決鍵盤問題擂涛,請使用IQKeyBoardManager读串。

總結

上述7個問題,是我暫時發(fā)現(xiàn)的可能在使用react-navigation遇到的問題撒妈,如果遇到其他問題歡迎加入QQ群397885169一起討論恢暖,解決。

如果在文章中遇到什么錯誤狰右,歡迎加群反饋杰捂,吐槽。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末棋蚌,一起剝皮案震驚了整個濱河市琼娘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌附鸽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞒瘸,死亡現(xiàn)場離奇詭異坷备,居然都是意外死亡,警方通過查閱死者的電腦和手機情臭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門省撑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赌蔑,“玉大人,你說我怎么就攤上這事竟秫⊥薰撸” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵肥败,是天一觀的道長趾浅。 經常有香客問我,道長馒稍,這世上最難降的妖魔是什么皿哨? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮纽谒,結果婚禮上证膨,老公的妹妹穿的比我還像新娘。我一直安慰自己鼓黔,他們只是感情好央勒,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澳化,像睡著了一般崔步。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肆捕,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天刷晋,我揣著相機與錄音,去河邊找鬼慎陵。 笑死眼虱,一個胖子當著我的面吹牛,可吹牛的內容都是我干的席纽。 我是一名探鬼主播捏悬,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼润梯!你這毒婦竟也來了过牙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤纺铭,失蹤者是張志新(化名)和其女友劉穎寇钉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舶赔,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡扫倡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竟纳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撵溃。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡疚鲤,死狀恐怖,靈堂內的尸體忽然破棺而出缘挑,到底是詐尸還是另有隱情集歇,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布语淘,位于F島的核電站诲宇,受9級特大地震影響,放射性物質發(fā)生泄漏亏娜。R本人自食惡果不足惜焕窝,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望维贺。 院中可真熱鬧它掂,春花似錦、人聲如沸溯泣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垃沦。三九已至客给,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肢簿,已是汗流浹背靶剑。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留池充,地道東北人桩引。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像收夸,于是被迫代替她去往敵國和親坑匠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容

  • react-navigation導航組件使用詳解 注意了卧惜,如果有小伙伴們發(fā)現(xiàn)運行作者提供的react-naviga...
    光強_上海閱讀 23,430評論 38 103
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評論 25 707
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫厘灼、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,029評論 4 62
  • 先跟偶像飯基友在獵德吃了個飯然后再去科韻路咽瓷。席間和路上吹了好多水设凹,也確認下自己之前了解的信息有沒有問題之類。 基友...
    涼風口香糖閱讀 818評論 0 0
  • 日復一日茅姜,就醒來围来,睡去 齒輪咬緊他的兄弟 鐘表邊敲邊叫不要靠近 今天過后是明天 看客沉沉睡去 夢里抬頭是風 低頭落雨
    送往勞來閱讀 139評論 0 0