2018-09-03

本文是基于最新的react-navigation^2.9.1來書寫的。

要感謝掛著鈴鐺的兔
看到一篇不錯的介紹,這里做下記錄

react-native-router-flux使用技巧(API篇)

識兔,一款用來識別圖片的開源項目,在未來還會添加更多有意思的東西

react-navigation的Demo

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

什么是react-navigation?

react-native從開源至今,一直存在幾個無法解決的毛病,偶爾就會復發讓人隱隱作痛,提醒你用的不是原生,其中包括列表的復用問題,導航跳轉不流暢的問題等等。
終于facebook坐不住了,在前一段時間開始推薦使用react-navigation,并且在0.44發布的時將之前一直存在的Navigator廢棄了。
react-navigation是致力于解決導航卡頓,數據傳遞,Tabbar和navigator布局,支持redux。雖然現在功能還不完善,但基本是可以在項目中推薦使用的。

屬性

react-navigation分為三個部分。
StackNavigator類似頂部導航條,用來跳轉頁面和傳遞參數。
TabNavigator類似底部標簽欄,用來區分模塊。
DrawerNavigator抽屜,類似從App左側滑出一個頁面,在這里不做講解。
下面會分開講解官網提供的配置方法,但順序可能會官網不一樣。

React-Navigation V2版使用教程

距離我上一個版本的react-navigation教程已經有1年多的時間了,雖然一直在縫縫補補,但那個教程真的老了。正好react-navigation V2版本也即將要正式發布了,趁著這次機會重新梳理一下教程,并把之前的坑和遺憾填補一下。

我會將本文分成三部分,第一部分是使用小技巧,第二部分是介紹API,第三部分是常用屬性方法。

跳轉

navigate('Detail',{
                   title:'圖片詳情',
                   url:item.url,
                   });

Detail:在StackNavigator中注冊的頁面,需要一一對應,才能跳轉到相應的頁面
title:在跳轉的頁面可以通過this.props.navigation.state.params.title獲取到這個參數。當然這個參數可以隨便填寫,都可以通過this.props.navigation.state.params.xxx獲取。

回調傳參

navigate('Detail',{
                   // 跳轉的時候攜帶一個參數去下個頁面
                   callback: (data)=>{
                         console.log(data); // 打印值為:'回調參數'
                     }
                   });

const {navigate,goBack,state} = this.props.navigation;
// 在第二個頁面,在goBack之前,將上個頁面的方法取到,并回傳參數,這樣回傳的參數會重走render方法
state.params.callback('回調參數');
goBack();

自定義

項目中基本是沒可能用自帶的那個導航條的,自帶導航條左側的按鈕永遠是藍色的,如果我們需要更改按鈕顏色,就需要用到自定義的功能了。

const StackOptions = ({navigation}) => {
    console.log(navigation);
    let {state,goBack} = navigation;

    // 用來判斷是否隱藏或顯示header
    const visible= state.params.isVisible;
    let header;
    if (visible === true){
        header = null;
    }
    const headerStyle = {backgroundColor:'#4ECBFC'};
    const headerTitle = state.params.title;
    const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white',fontWeight:'500'}
    const headerBackTitle = false;
    const headerLeft = (
        <Button
            isCustom={true}
            customView={
                            <Icon
                                name='ios-arrow-back'
                                size={30}
                                color='white'
                                style={{marginLeft:13}}
                            />
                        }
            onPress={()=>{goBack()}}
        />
    );
    return {headerStyle,headerTitle,headerTitleStyle,headerBackTitle,headerLeft,header}
};

然后通過下面的方法調用就可以自定制導航了。

const MyApp = StackNavigator({
    MyTab: {
        screen: MyTab,
    },
    Detail: {
        screen: Detail,
        navigationOptions: ({navigation}) => StackOptions({navigation})
    },
)};

在頁面中使用的時候,在跳轉頁面的時候需要傳遞title參數,才能看到效果哦。

自定義tabbar

早上有人問我,tabbar的圖標可不可以使用原圖,選中狀態下可不可以設置其他圖標。研究了一下官方文檔,發現tabBarIcon除了tintColor還有另一個屬性,用來判斷選中狀態的focused

 tabBarIcon: ({tintColor,focused}) => (
                focused
                    ?
                    <Image
                        source={{uri : '識兔'}}
                        style={tabBarIcon}
                    />
                    :
                    <Image
                        source={{uri : '干貨'}}
                        style={[tabBarIcon, {tintColor: tintColor}]}
                    />
            ),

通過判斷focused,選中狀態下使用識兔圖標,未選中狀態使用干貨圖標。
如果想使用圖標原來的樣子,那就將styletintColor去掉,這樣就會顯示圖標原本的顏色。

再封裝

export const TabOptions = (tabBarTitle,normalImage,selectedImage,navTitle) => {
    // console.log(navigation);
    const tabBarLabel = tabBarTitle;
    console.log(navTitle);
    const tabBarIcon = (({tintColor,focused})=> {
        return(
            focused
                ?
                <Image
                    source={{uri : normalImage}}
                    style={[TabBarIcon, {tintColor: tintColor}]}
                />
                :
                <Image
                    source={{uri : selectedImage}}
                    style={[TabBarIcon, {tintColor: tintColor}]}
                />
        )
    });
    const headerTitle = navTitle;
    const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white'};
    // header的style
    const headerStyle = {backgroundColor:'#4ECBFC'};
    return {tabBarLabel,tabBarIcon,headerTitle,headerTitleStyle,headerStyle};
};

在static中使用this方法

我之前文章中是將navaigationOptions的方法寫在了app.js中,沒有在頁面中通過static navaigationOptions來初始化頁面,這段時間剛好有人問,所以在這里就寫一下該怎么弄。

首先需要在componentDidMount(){}中動態的添加點擊事件
屬性給params
componentDidMount(){

    this.props.navigation.setParams({
        title:'自定義Header',
        navigatePress:this.navigatePress
    })
}

navigatePress = () => {
    alert('點擊headerRight');
    console.log(this.props.navigation);
}

接下來就可以通過params方法來獲取點擊事件了
static navigationOptions = ({ navigation, screenProps }) => ({
        title: navigation.state.params?navigation.state.params.title:null,
        headerRight:(
            <Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
                返回
            </Text>
        )
});

讓安卓實現push動畫

之前我群里的討論怎么讓安卓實現類似iOS的push動畫,后來翻看官方issues的時候,真的發現了實現push動畫的代碼,在這里共享下

// 先引入這個方法
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';

// 在StackNavigator配置headerMode的地方,使用transitionConfig添加
{
    headerMode: 'screen',
    transitionConfig:()=>({
        screenInterpolator:CardStackStyleInterpolator.forHorizontal,
    })
}

關于goBack返回指定頁面

react-navigation是提供了goBack()到指定頁面的方法的,那就是在goBack()中添加一個參數,但當你使用goBack('Main')的時候,你會發現并沒有跳轉,原因是react-navigation默認goBack()中的參數是系統隨機分配的key,而不是手動設置的routeName,而方法內部又沒有提供可以獲得key的方法,所以這里只能通過修改源碼將key換成routeName了。
下面的內容直接引用了hello老文的內容

把項目/node_modules/react-navigation/src/routers/StackRouter.js文件里的 
const backRoute = state.routes.find((route: *) => route.key === action.key); 
改成 const backRoute = state.routes.find(route => route.routeName === action.key);

但不是很完美, 這里的component要填想返回的組件的前一個組件的routeName, 比如你的棧里順序是home1, home2, home3, home4, 在home4里要返回home2, 使用this.props.navigation.goBack('home3');; 并且又會帶出一個問題: goBack()方法沒反應了, 必須加個null進去, 寫成goBack(null)...

關于goBack返回指定頁面的修改完善版

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,
      };
    }
  }

感謝群友conan的貢獻,將源碼改成上面的樣子,就可以使用goBack()返回指定頁面了,這樣的優點不言而喻,但缺點就是每次調用goBack(),如果只是簡單的返回上一頁需要加上null參數,類似這樣goBack(null)

如果這樣修改,在滑動返回的時候,會有很大幾率讓項目卡死,請注意使用該方法,推薦集成redux。

關于快速點擊會導致多次跳轉的問題解決辦法

感謝群友編程大叔的貢獻,如果想解決快速點擊跳轉的問題,需要修改部分源碼。

修改react-navigation目錄下,scr文件夾中的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,
        }),
      ),
  };
}

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

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

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

 android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"

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

API

createSwitchNavigator

SwitchNavigator的目的是一次只顯示一個屏幕。默認情況下,它不處理回退操作,并在您切換時將路由重置為默認狀態。這是我們從登錄流程(包含注冊,登錄,忘記密碼等)到主屏幕的必要流程。

這個方法在1.x中叫做SwitchNavigator,在2.x中統一命名為createSwitchNavigator
createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig);

RouteConfigs

路由的配置表,詳細配置可以參考下面的createStackNavigator

SwitchNavigatorConfig

SwitchNavigator屬性

  • initialRouteName - 第一次加載時初始選項卡路由的routeName。
  • resetOnBlur - 切換離開屏幕時,重置所有嵌套導航器的狀態。默認為true。
  • paths - 提供routeNamepath的深度鏈接,它會覆蓋RouteConfigs中設置的路徑。
  • backBehavior - 后退按鈕是否會導致標簽切換到初始路由?如果是,則設置為initialRoute,否則none。默認為none
export default createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
);

createStackNavigator

配置路由屬性和參數

這個方法在1.x中叫做StackNavigator,在2.x中統一命名為createSwitchNavigator
createStackNavigator(RouteConfigs, StackNavigatorConfig);

RouteConfigs

  • screen - 對應界面名稱,是一個React組件
  • path - 深度鏈接路徑,從其他App或者web跳轉到該App需要設置該路徑
  • navigationOptions - 用于屏幕的默認導航選項

StackNavigatorConfig

可選的路由屬性
  • initialRouteName - 設置默認屏幕。必須為路由配置中的某個screen。
  • initialRouteParams - 初始路由路線的參數。
  • navigationOptions - 用于屏幕的默認導航選項。
  • paths - 覆蓋路由配置中設置的路徑的映射。
可選的視覺選項
  • mode - 定義渲染和轉換的樣式

    • card - 使用標準的iOS和Android屏幕轉換。這是默認屬性。
    • modal - 使屏幕從底部滑入,這是一種常見的iOS模式。只適用于iOS,對Android沒有影響。
  • headerMode - 定義如何呈現標題

    • float - 在屏幕更改時渲染保留在頂部的單個標題和動畫。這是iOS上的常見效果。
    • screen - 每個屏幕都附有一個標題,標題與屏幕一起淡入和淡出。這是Android上的常見效果。
    • none - 不會顯示標題。
  • headerTransitionPreset - 指定標題在headerMode: float啟用時應該如何從一個屏幕切換到另一個屏幕。

    • fade-in-place - 標題組件在不移動的情況下淡入淡出,類似于iOS的Twitter,Instagram和Facebook應用程序。這是默認值。
    • uikit - iOS的默認效果。
  • cardStyle - 使用此道具覆蓋或擴展堆棧中單個卡的默認樣式。

  • transitionConfig - 函數返回與默認屏幕轉換合并的對象(查看類型定義中的TransitionConfig )。提供的函數將傳遞以下參數:

    • transitionProps - 新屏幕的過渡轉換。
    • prevTransitionProps - 舊屏幕的過渡轉換。
    • isModal - 指定屏幕是否為模態。
  • onTransitionStart - 跳轉動畫即將開始時要調用的函數。

  • onTransitionEnd - 跳轉動畫完成后調用的函數。

navigationOptions

導航頁面的屬性和方法

  • title - 可用作的headerBackTitle的標題。此外,將用作tabBarLabel(如果嵌套在TabNavigator中)或drawerLabel(如果嵌套在DrawerNavigator中)的回退標題。

  • header - 返回一個React元素,用來作為標題。設置null會隱藏標題。

  • headerTitle - 可以傳入字符串,React Element,React Component。默認是用上面的title作為標題。當使用Component時,它接受allowFontScaling,stylechildren作為屬性。title會被放在children中。

  • headerTitleAllowFontScaling - 標題字體是否應該縮放以遵循系統設置。默認值為true。

  • headerBackImage - 接受React Element或者Component用來顯示自定義的后退按鈕中的圖片。當使用組件時,它會得到(tintColor,title)參數。默認為react-navigation/views/assets/back-icon.png路徑下的圖片,這是區分平臺的默認圖標。

  • headerBackTitle - iOS上后退按鈕使用的文字,傳遞null會禁用標簽。默認為前一場景headerTitle。

  • headerTruncatedBackTitle - 當后退按鈕使用的標題字符串headerBackTitle不適合屏幕時(比如說文字過長),會默認顯示Back

  • headerRight - 接受React Element將會顯示在標題的右側。

  • headerLeft - 接受React Element或者React Component將會顯示在標題的左側。當傳遞一個組件的時候,會得到(onPress,title,titleStyle還有更多,請參考Header.js以獲得完整的列表)。

  • headerStyle - 標題的樣式

  • headerForceInset - 允許將forceInset對象傳遞給標題中,使用的內部SafeAreaView。

  • headerTitleStyle - 標題組件的樣式

  • headerBackTitleStyle - 標題上后退按鈕文字樣式

  • headerTintColor - 標題組件的色調

  • headerPressColorAndroid - 材質紋波的顏色(僅限Android> = 5.0)

  • headerTransparent - 默認為false。如果為true標題將沒有背景,除非你明確提供了headerStyleheaderBackground

  • headerBackground - 將此與headerTransparent一起使用,以提供一個組件在標題的背景中呈現。例如,您可以將其用于模糊視圖,以創建半透明標題。

  • gesturesEnabled - 是否可以使用手勢來返回到上一頁。在iOS上默認為true,在Android上為false

  • gestureResponseDistance - 用于覆蓋觸摸從屏幕邊緣開始識別手勢的距離的對象。它具有以下屬性:

    • horizontal - number - 水平方向的距離。默認為25。
    • vertical - number - 垂直方向的距離。默認為135。
  • gestureDirection - 傳遞字符串用來覆蓋關閉手勢的方向。default為正常行為或inverted從右到左滑動。

Navigator Props

由StackNavigator(...)創建的導航器組件采用以下道具:

  • screenProps - 將其他選項傳遞給子屏幕

createTabNavigator

createTabNavigator已棄用。請改用createBottomTabNavigator和/或createMaterialTopTabNavigator。

createBottomTabNavigator

屏幕底部的簡單標簽欄,可讓您在不同路由之間切換。路由是被懶惰初始化的 - 它們的屏幕組件直到第一次選中時才會初始化。

這個方法在1.x中叫做TabNavigator,在2.x中統一命名為createBottomTabNavigator
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);

RouteConfigs

屬性請參考createStackNavigator
它的navigationOptionscreateStackNavigator不一樣,下面會有說明。

BottomTabNavigatorConfig

  • initialRouteName - 第一次加載時初始選項卡路由的routeName。

  • order - 定義選項卡順序的routeNames數組。

  • paths - 提供routeNamepath的深度鏈接,它會覆蓋RouteConfigs中設置的路徑。

  • backBehavior - 后退按鈕是否會導致標簽切換到初始路由?如果是,則設置為initialRoute,否則none。默認為initialRoute。

  • tabBarComponent - Options,覆蓋用作標簽欄的組件。

  • tabBarOptions - 標簽欄具有如下屬性:

    • activeTintColor - 活動選項卡的標簽和圖標顏色。(選中)
    • activeBackgroundColor - 活動選項卡的背景顏色。(選中)
    • inactiveTintColor - 非活動選項卡的標簽和圖標顏色。(未選中)
    • inactiveBackgroundColor - 非活動選項卡的背景顏色。(未選中)
    • showLabel - 是否顯示標簽,默認為true
    • style - 標簽欄的樣式。
    • labelStyle - 標簽欄文字的樣式。
    • tabStyle - 選項卡的樣式。
    • allowFontScaling - 標題字體是否應該縮放以遵循系統設置。默認值為true。

navigationOptions

標簽欄的屬性和方法

  • title - 通用標題可以用作headerTitletabBarLabel

  • tabBarVisible - 顯示或隱藏底部標簽欄,默認為true,不隱藏。

  • tabBarIcon - React Element或給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在標簽欄中。

  • tabBarLabel - 接收字符串、React Element或者給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在標簽欄中。如果未定義,會使用title作為默認值。如果想要隱藏,可以參考上面的tabBarOptions.showLabel

  • tabBarOnPress - 標簽欄點擊事件回調,接受一個對象,其中包含如下:

[圖片上傳失敗...(image-d10d-1535967589937)]

tabBarOnPress: async (obj: any) => {
            console.log(obj);
            try {
                const userData = await AsyncStorage.getItem('USER_INFO');
                if (userData) {
                    obj.defaultHandler();
                }
                else {
                    obj.navigation.navigate('Login');
                }
            } catch (e) {
                Toast.show(e.message, 'center', 1000);
            }
        }

createMaterialTopTabNavigator

實現了類似react-native-scrollable-tab-view的左右滾動效果,但每個tab頁是沒有懶加載的,就是說,當使用這個生成導航的時候,每個頁面都會初始化,對內存影響較大。
這個導航是基于react-native-tab-view實現的,如果有需要可以研究。

createMaterialTopTabNavigator(RouteConfigs, TabNavigatorConfig);

RouteConfigs

屬性請參考createStackNavigator。

TabNavigatorConfig

  • initialRouteName - 第一次加載時初始選項卡路由的routeName。

  • order - 定義選項卡順序的routeNames數組。

  • paths - 提供routeNamepath的深度鏈接,它會覆蓋RouteConfigs中設置的路徑。

  • backBehavior - 后退按鈕是否會導致標簽切換到初始路由?如果是,則設置為initialRoute,否則none。默認為initialRoute。

  • swipeEnabled - 是否允許在標簽之間滑動。

  • animationEnabled - 改變標簽時是否使用動畫。

  • configureTransition - 給定currentTransitionProps和nextTransitionProps返回一個描述選項卡之間動畫的配置對象的函數。

  • initialLayout - 包含初始height和可選對象width,可以傳遞以防止react-native-tab-view出現一幀的延遲。

  • tabBarComponent - Options,覆蓋用作標簽欄的組件。

  • tabBarOptions - 標簽欄具有如下屬性:

    • activeTintColor - 活動選項卡的標簽和圖標顏色。(選中)
    • inactiveTintColor - 非活動選項卡的標簽和圖標顏色。(未選中)
    • showIcon - 是否顯示標簽圖標,默認為false。
    • showLabel - 是否顯示標簽,默認為true
    • upperCaseLabel - 是否使標簽大寫,默認為true。
    • pressColor - 紋波的顏色(僅限Android> = 5.0)。
    • pressOpacity - 按下標簽的不透明度(僅iOS和Android <5.0)。
    • scrollEnabled - 是否啟用可滾動標簽。
    • tabStyle - 選項卡的樣式。
    • indicatorStyle - 選項卡指示符的樣式(選項卡底部線的顏色)。
    • labelStyle - 標簽欄文字的樣式。
    • iconStyle - 選項卡圖標的樣式。
    • style - 標簽欄的樣式。
    • allowFontScaling - 標題字體是否應該縮放以遵循系統設置。默認值為true。

navigationOptions

  • title - 通用標題可以用作headerTitletabBarLabel。
  • swipeEnabled - 如果未設置,則遵循TabNavigatorConfig選項swipeEnabled。啟用或禁用標簽之間的滑動操作為truefalse
  • tabBarIcon - React Element或給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在標簽欄中。
  • tabBarLabel - 接收字符串、React Element或者給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在標簽欄中。如果未定義,會使用title作為默認值。如果想要隱藏,可以參考上面的tabBarOptions.showLabel。
  • tabBarOnPress - 標簽欄點擊事件回調,接受一個對象,其中包含如下:

[圖片上傳失敗...(image-8865d7-1535967589937)]

tabBarOnPress: async (obj: any) => {
            console.log(obj);
            try {
                const userData = await AsyncStorage.getItem('USER_INFO');
                if (userData) {
                    obj.defaultHandler();
                }
                else {
                    obj.navigation.navigate('Login');
                }
            } catch (e) {
                Toast.show(e.message, 'center', 1000);
            }
        }

createDrawerNavigator

創建側邊欄導航,有一些坑,需要用過才知道。

createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

RouteConfigs

屬性請參考createStackNavigator。

DrawerNavigatorConfig

  • drawerWidth - 抽屜的寬度或返回一個新的函數。

  • drawerPosition - 抽屜出現的方向leftright,默認left

  • contentComponent - 用于呈現抽屜內容的組件,例如導航項。接收navigation抽屜的屬性。默認為DrawerItems。有關更多信息,請參見下文。

  • contentOptions - 配置抽屜內容,請參見下文。

  • useNativeAnimations - 啟用本地動畫。默認是true。

  • drawerBackgroundColor - 設置抽屜的背景背景。默認是white。

  • initialRouteName - 第一次加載時初始選項卡路由的routeName。

  • order - 定義選項卡順序的routeNames數組。

  • paths - 提供routeNamepath的深度鏈接,它會覆蓋RouteConfigs中設置的路徑。

  • backBehavior - 后退按鈕是否會導致標簽切換到初始路由?如果是,則設置為initialRoute,否則none。默認為initialRoute。

contentComponent

提供自定義的抽屜效果
抽屜的默認組件是可滾動的,只包含RouteConfig中路由的鏈接。您可以輕松地覆蓋默認組件,以向抽屜中添加頁眉,頁腳或其他內容。默認情況下,抽屜可滾動并支持iPhone X安全區域。如果您自定義內容,請務必將內容包裝在SafeAreaView中

DrawerItemscontentOptions

  • items - 路由數組,可以修改或覆蓋。

  • activeItemKey - 識別活動路線的key。

  • activeTintColor - 活動標簽的標簽和圖標顏色。(選中)

  • activeBackgroundColor - 活動標簽的背景顏色。(選中)

  • inactiveTintColor - 不活動標簽的標簽和圖標顏色。(未選中)

  • inactiveBackgroundColor - 不活動標簽的背景顏色。(未選中)

  • onItemPress(route) - 按下某個Item時調用的函數。

  • itemsContainerStyle - item內容的樣式。

  • itemStyle - 單個Item樣式,其中可以包含圖標和標簽。

  • labelStyle - 當標簽是字符串時,會覆蓋文字的樣式。

  • activeLabelStyle - 當標簽是字符串時,會覆蓋選中的文字樣式。

  • inactiveLabelStyle - 當標簽是字符串時,會覆蓋未選中的文字樣式。

  • iconContainerStyle - 用來覆蓋icon的樣式

Screen Navigation Options

  • title - 通用標題可以用作headerTitletabBarLabel

  • drawerLabel - 可以傳入字符串,React Element或給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在抽屜邊欄中。當不設置時,默認使用title

  • drawerIcon - React Element或給定{focused:boolean,tintColor:string}的函數返回一個React.Node,用來顯示在抽屜邊欄中。

  • drawerLockMode - 指定抽屜的鎖定模式。這也可以通過在頂級路由器上使用screenProps.drawerLockMode動態更新。

enum('unlocked', 'locked-closed', 'locked-open')

createMaterialBottomTabNavigator

這個方法在2.0正式版中被砍掉了,但官方文檔沒有更新,如果喜歡material風格,可以參考react-native-material-bottom-navigation

常用屬性方法

這部分會分為createStackNavigatorcreateDrawerNavigator兩部分,因為它們屬性不太一樣。

createStackNavigator

常用方法

[圖片上傳失敗...(image-c747f-1535967589936)]

在新版的react-navigation中實現了很多常用的api,比如說pushpoppopToTop等常用方法,在本文中會將屬性和使用方法簡單說明。

NavigationActions

  • Navigate - 用來跳轉到其他路由的方法
    • routeName - String - 必須 - 在RouteConfigs中注冊過的路由名稱
    • params - Object - 可選 - 傳遞的參數
    • action - Object - 可選 - (高級)如果屏幕是導航器,則在子路由器中運行的子操作。本文檔中描述的任何一項操作都可以設置為子操作。
    • key - String - 可選 - 要導航到的路線的標識符。如果它已經存在,則返回到此路線。
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  params: {},
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }),
});
this.props.navigation.dispatch(navigateAction);

  • Back - 用來返回到上一個路由或其他路由

    • Key - String | null - 如果設置,導航將從給定的鍵返回。如果為空,導航將返回到上一級。
import { NavigationActions } from 'react-navigation';
const backAction = NavigationActions.back({
  key: 'Profile',
});
this.props.navigation.dispatch(backAction);

  • SetParams

在調用SetParams時,路由器將產生一個新的狀態,該狀態已經改變了由key標識的特定路由參數

* `params` - Object - 可選 - 新的參數被合并到現有的路徑參數中。
* `key` - String - 必須 - 獲取新參數的路由鍵。

import { NavigationActions } from 'react-navigation';

const setParamsAction = NavigationActions.setParams({
  params: { title: 'Hello' },
  key: 'screen-123',
});
this.props.navigation.dispatch(setParamsAction);

  • Reset - 重置路由

Reset操作將重置整個導航狀態并將其替換為新的導航。

* `index` - number - 必須 - 導航中`routes`活動路由的索引`state`。

* `actions` - array - 必須 - 將替換導航數組。
* `key` - string | null - 可選 - 如果設置,具有給定鍵的導航器將重置。如果為null,則根導航器將被重置。

import { StackActions, NavigationActions } from 'react-navigation';
const resetAction = StackActions.reset({
  index: 0,
  actions: [NavigationActions.navigate({ routeName: 'Profile' })],
});
this.props.navigation.dispatch(resetAction);

  • Replace - 用新的route替換當前的route

Replace操作將給定key上的路線替換為另一條路線。

* `key` - string - 必須 - 要替換??路由的`key`。

* `newKey` - string - 用于替換路由的`key`。如果未提供,則自動生成。
* `routeName` - string - 用于替換路由的`routeName`。
* `params` - object - 要傳入替換路由的參數。
* `action` - object - 可選的子操作。

  • Push - 入棧

Push操作會在堆棧頂部添加一條路徑并向前導航。這與之前的不同之處在于,如果某個組件已經存在路由中,navigate則會彈出到堆棧中的較早版本。Push將始終添加在頂部,因此可以多次安裝組件。

* `routeName` - string - 要跳轉路由的`routeName`。

* `params` - object - 傳遞的參數,可以通過(this.props.navigation.state.params)找到。
* `action` - 子操作。

  • pop(n) - 出棧

Pop操作將使您回到堆棧中的前一個屏幕。n參數允許您指定要多少個屏幕出棧。

* `n` - number - 要出棧的屏幕數量。

  • PopToTop - 回到棧頂

PopToTop操作會將您帶回堆棧中的第一個屏幕,解除所有其他屏幕。它的功能與StackActions.pop({n: currentIndex})類似。

----------------------------------------------新老版本的分割線--------------------------------------------------------

screenProps

之前是沒有介紹這個屬性的,但經過這么久發現,很多人都不知道這個屬性,不知道它能干嘛,在這里我就簡單的介紹下

screenProps:react-navigation自帶的一個屬性,屬于navigationOptions的一個屬性,可以全局控制navigationOptions中的某些值,比如說你想做換膚功能,修改這個屬性絕對是最簡單的方式。

// 假設App就是項目中的入口文件,如果還不知道,可以看下Demo,在這里我將主題色通過screenProps屬性修改成'red'
<App screenProps={{themeColor:'red'}}>

// 在頁面中就可以通過screenProps來直接改變了,這個在Demo
中的Test2里面

static navigationOptions = ({navigation,screenProps}) => ({
        // 這里面的屬性和App.js的navigationOptions是一樣的。
                headerStyle:{backgroundColor:screenProps?
                screenProps.themeColor:
                '#4ECBFC'},

    )
})

StackNavigator 基礎用法/屬性介紹

const MyApp = StackNavigator({
    // 對應界面名稱
    MyTab: {
        screen: MyTab,
    },
    Detail: {
        screen: Detail,
        navigationOptions:{
            headerTitle:'詳情',
            headerBackTitle:null,
        }
    },
}, {
    headerMode: 'screen',
});

導航配置

screen:對應界面名稱,需要填入import之后的頁面。

navigationOptions:配置StackNavigator的一些屬性。

  • title:標題,如果設置了這個導航欄和標簽欄的title就會變成一樣的,所以不推薦使用這個方法。
  • header:可以設置一些導航的屬性,當然如果想隱藏頂部導航條只要將這個屬性設置為null就可以了。
  • headerTitle:設置導航欄標題,推薦用這個方法。
  • headerBackTitle:設置跳轉頁面左側返回箭頭后面的文字,默認是上一個頁面的標題??梢宰远x,也可以設置為null
  • headerTruncatedBackTitle:設置當上個頁面標題不符合返回箭頭后的文字時,默認改成"返回"。(上個頁面的標題過長,導致顯示不下,所以改成了短一些的。)
  • headerRight:設置導航條右側。可以是按鈕或者其他。
  • headerLeft:設置導航條左側。可以是按鈕或者其他。
  • headerStyle:設置導航條的樣式。背景色,寬高等。如果想去掉安卓導航條底部陰影可以添加elevation: 0,iOS下用shadowOpacity: 0。
  • headerTitleStyle:設置導航條文字樣式。安卓上如果要設置文字居中,只要添加alignSelf:'center'就可以了。在安卓上會遇到,如果左邊有返回箭頭導致文字還是沒有居中的問題,最簡單的解決思路就是在右邊也放置一個空的按鈕。
在最新版本的react-navigation中,安卓居中可以使用 flex:1, textAlign: 'center'來實現。
  • headerBackTitleStyle:設置導航條返回文字樣式。
  • headerTintColor:設置導航欄文字顏色??偢杏X和上面重疊了。
  • headerPressColorAndroid:安卓獨有的設置顏色紋理,需要安卓版本大于5.0
  • gesturesEnabled:是否支持滑動返回手勢,iOS默認支持,安卓默認關閉
  • gestureResponseDistance:對象覆蓋觸摸從屏幕邊緣開始的距離,以識別手勢。 它需要以下屬性:
    • horizontal - number - 水平方向的距離 默認為25。
    • vertical - number - 垂直方向的距離 默認為135。
// 設置滑動返回的距離
gestureResponseDistance:{horizontal:300},

注:beta13新出的東西,挺有意思,以后可以手動控制返回了

導航視覺效果

mode:定義跳轉風格。

  • card:使用iOS和安卓默認的風格。
  • modal:iOS獨有的使屏幕從底部畫出。類似iOS的present效果

headerMode:邊緣滑動返回上級頁面時動畫效果。

  • float:iOS默認的效果,可以看到一個明顯的過渡動畫。
  • screen:滑動過程中,整個頁面都會返回。
  • none:沒有動畫。

cardStyle:自定義設置跳轉效果。

transitionConfig: 自定義設置滑動返回的配置。
onTransitionStart:當轉換動畫即將開始時被調用的功能。
onTransitionEnd:當轉換動畫完成,將被調用的功能。

path:路由中設置的路徑的覆蓋映射配置。
initialRouteName:設置默認的頁面組件,必須是上面已注冊的頁面組件。
initialRouteParams:初始路由的參數。

path:path屬性適用于其他app或瀏覽器使用url打開本app并進入指定頁面。path屬性用于聲明一個界面路徑,例如:【/pages/Home】。此時我們可以在手機瀏覽器中輸入:app名稱://pages/Home來啟動該App,并進入Home界面。

TabNavigator 基礎用法/屬性介紹

const MyTab = TabNavigator({
    ShiTu: {
        screen: ShiTu,
        navigationOptions:{
            tabBarLabel: '識兔',
            tabBarIcon: ({tintColor}) => (
                <Image
                    source={{uri : '識兔'}}
                    style={[tabBarIcon, {tintColor: tintColor}]}
                />
            ),
        },
    }, {
    tabBarPosition: 'bottom',
    swipeEnabled:false,
    animationEnabled:false,
    tabBarOptions: {
        style: {
            height:49
        },
        activeBackgroundColor:'white',
        activeTintColor:'#4ECBFC',
        inactiveBackgroundColor:'white',
        inactiveTintColor:'#aaa',
        showLabel:false,
    }
});

屏幕導航配置

screen:和導航的功能是一樣的,對應界面名稱,可以在其他頁面通過這個screen傳值和跳轉。
navigationOptions:配置TabNavigator的一些屬性

  • title:標題,會同時設置導航條和標簽欄的title,還是不推薦這種方式。
  • tabBarVisible:是否隱藏標簽欄。默認不隱藏(true)
  • tabBarIcon:設置標簽欄的圖標。需要給每個都設置。
  • tabBarLabel:設置標簽欄的title。推薦這個方式。
  • tabBarOnPress:設置tabBar的點擊事件,內部提供了兩個屬性,一個方法(obj)。
    beta13新添加的方法,使用方式有些奇葩,如果想要使用,請參照下面的代碼
tabBarOnPress:(obj)=>{
            console.log(obj);

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

標簽欄配置

tabBarPosition:設置tabbar的位置,iOS默認在底部,安卓默認在頂部。(屬性值:'top','bottom')
swipeEnabled:是否允許在標簽之間進行滑動。
animationEnabled:是否在更改標簽時顯示動畫。
lazy:是否根據需要懶惰呈現標簽,而不是提前制作,意思是在app打開的時候將底部標簽欄全部加載,默認false,推薦改成true哦。
initialRouteName: 設置默認的頁面組件
backBehavior:按 back 鍵是否跳轉到第一個Tab(首頁), none 為不跳轉

tabBarOptions:配置標簽欄的一些屬性

iOS屬性
  • activeTintColor:label和icon的前景色 活躍狀態下(選中)。
  • activeBackgroundColor:label和icon的背景色 活躍狀態下(選中) 。
  • inactiveTintColor:label和icon的前景色 不活躍狀態下(未選中)。
  • inactiveBackgroundColor:label和icon的背景色 不活躍狀態下(未選中)。
  • showLabel:是否顯示label,默認開啟。
  • style:tabbar的樣式。
  • labelStyle:label的樣式。
安卓屬性
  • activeTintColor:label和icon的前景色 活躍狀態下(選中) 。
  • inactiveTintColor:label和icon的前景色 不活躍狀態下(未選中)。
  • showIcon:是否顯示圖標,默認關閉。
  • showLabel:是否顯示label,默認開啟。
  • style:tabbar的樣式。
  • labelStyle:label的樣式。
  • upperCaseLabel:是否使標簽大寫,默認為true。
  • pressColor:material漣漪效果的顏色(安卓版本需要大于5.0)。
  • pressOpacity:按壓標簽的透明度變化(安卓版本需要小于5.0)。
  • scrollEnabled:是否啟用可滾動選項卡。
  • tabStyle:tab的樣式。
  • indicatorStyle:標簽指示器的樣式對象(選項卡底部的行)。安卓底部會多出一條線,可以將height設置為0來暫時解決這個問題。
  • labelStyle:label的樣式。
  • iconStyle:圖標的樣式。
    ps:很多人問我,為什么安卓上的tabbar文字會下移, 是因為安卓比iOS多了一個屬性,就是iconStyle,通過設置labelStyleiconStyle兩個樣式,外加style的高度,來使效果更佳合理.
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容