React Native——react-navigation的使用

xiaoyanger發表於2017-07-21

React Native中,官方已經推薦使用react-navigation來實現各個介面的跳轉和不同板塊的切換。react-navigation主要包括三個元件:

  • StackNavigator 導航元件
  • TabNavigator 切換元件
  • DrawerNavigator 抽屜元件

StackNavigator用於實現各個頁面之間的跳轉,TabNavigator用來實現同一個頁面上不同介面的切換,DrawerNavigator 可以實現側滑的抽屜效果。

StackNavigator

StackNavigator元件採用堆疊式的頁面導航來實現各個介面跳轉。它的建構函式:

StackNavigator(RouteConfigs, StackNavigatorConfig)複製程式碼

RouteConfigsStackNavigatorConfig兩個引數。

RouteConfigs

RouteConfigs 參數列示各個頁面路由配置,類似於android原生開發中的AndroidManifest.xml,它是讓導航器知道需要導航的路由對應的頁面。

const RouteConfigs = {
    Home: {
        screen: HomePage,
        navigationOptions: ({navigation}) => ({
            title: '首頁',
        }),
    },
    Find: {
        screen: FindPage,
        navigationOptions: ({navigation}) => ({
            title: '發現',
        }),
    },
    Mine: {
        screen: MinePage,
        navigationOptions: ({navigation}) => ({
            title: '我的',
        }),
    },
};複製程式碼

這裡給導航器配置了三個頁面,HomeFindMine為路由名稱,screen屬性值HomePageFindPageMinePage為對應路由的頁面。

navigationOptions為對應路由頁面的配置選項:

  • title - 可以作為頭部標題headerTitle,或者Tab標題tabBarLabel
  • header - 自定義的頭部元件,使用該屬性後系統的頭部元件會消失
  • headerTitle - 頭部的標題,即頁面的標題
  • headerBackTitle - 返回標題,預設為title
  • headerTruncatedBackTitle - 返回標題不能顯示時(比如返回標題太長了)顯示此標題,預設為“Back”
  • headerRight - 頭部右邊元件
  • headerLeft - 頭部左邊元件
  • headerStyle - 頭部元件的樣式
  • headerTitleStyle - 頭部標題的樣式
  • headerBackTitleStyle - 頭部返回標題的樣式
  • headerTintColor - 頭部顏色
  • headerPressColorAndroid - Android 5.0以上MD風格的波紋顏色
  • gesturesEnabled - 否能側滑返回,iOS預設trueAndroid預設false
StackNavigatorConfig

StackNavigatorConfig參數列示導航器的配置,包括導航器的初始頁面、各個頁面之間導航的動畫、頁面的配置選項等等:

const StackNavigatorConfig = {
    initialRouteName: 'Home',
    initialRouteParams: {initPara: '初始頁面引數'},
    navigationOptions: {
        title: '標題',
        headerTitleStyle: {fontSize: 18, color: '#666666'},
        headerStyle: {height: 48, backgroundColor: '#fff'},
    },
    paths: 'page/main',
    mode: 'card',
    headerMode: 'screen',
    cardStyle: {backgroundColor: "#ffffff"},
    transitionConfig: (() => ({
        screenInterpolator: CardStackStyleInterpolator.forHorizontal,
    })),
    onTransitionStart: (() => {
        console.log('頁面跳轉動畫開始');
    }),
    onTransitionEnd: (() => {
        console.log('頁面跳轉動畫結束');
    }),
};複製程式碼
  • initialRouteName - 導航器元件中初始顯示頁面的路由名稱,如果不設定,則預設第一個路由頁面為初始顯示頁面
  • initialRouteParams - 給初始路由的引數,在初始顯示的頁面中可以通過this.props.navigation.state.params來獲取
  • navigationOptions - 路由頁面的配置選項,它會被RouteConfigs 引數中的 navigationOptions的對應屬性覆蓋。
  • paths - 路由中設定的路徑的覆蓋對映配置
  • mode - 頁面跳轉方式,有cardmodal兩種,預設為card
    • card - 原生系統預設的的跳轉
    • modal - 只針對iOS平臺,模態跳轉
  • headerMode - 頁面跳轉時,頭部的動畫模式,有floatscreennone三種:
    • float - 漸變,類似iOS的原生效果
    • screen - 標題與螢幕一起淡入淡出
    • none - 沒有動畫
  • cardStyle - 為各個頁面設定統一的樣式,比如背景色,字型大小等
  • transitionConfig - 配置頁面跳轉的動畫,覆蓋預設的動畫效果
  • onTransitionStart - 頁面跳轉動畫即將開始時呼叫
  • onTransitionEnd - 頁面跳轉動畫一旦完成會馬上呼叫

頁面的配置選項navigationOptions通常還可以在對應頁面中去靜態配置,比如在HomePage頁面中:

export default class HomePage extends Component {

    // 配置頁面導航選項
    static navigationOptions = ({navigation}) => ({
        title: 'HOME',
        titleStyle: {color: '#ff00ff'},
        headerStyle:{backgroundColor:'#000000'}
    });

    render() {
        return (
            <View></View>
        )
    };
}複製程式碼

同樣地,在頁面裡面採用靜態的方式配置navigationOptions中的屬性,會覆蓋StackNavigator建構函式中兩個引數RouteConfigsStackNavigatorConfig配置的navigationOptions裡面的對應屬性。navigationOptions中屬性的優先順序是:
頁面中靜態配置 > RouteConfigs > StackNavigatorConfig

有了RouteConfigsStackNavigatorConfig兩個引數,就可以構造出一個導航器元件StackNavigator,直接引用該元件:

const Navigator = StackNavigator(RouteConfigs, StackNavigatorConfig);

export default class MainComponent extends Component {
    render() {
        return (
            <Navigator/>
        )
    };
}複製程式碼

已經配置好導航器以及對應的路由頁面了,但是要完成頁面之間的跳轉,還需要navigation

在導航器中的每一個頁面,都有navigation屬性,該屬性有以下幾個屬性/方法:

  • navigate - 跳轉到其他頁面
  • state - 當前頁面導航器的狀態
  • setParams - 更改路由的引數
  • goBack - 返回
  • dispatch - 傳送一個action

呼叫這個方法可以跳轉到導航器中的其他頁面,此方法有三個引數:
routeName 導航器中配置的路由名稱
params 傳遞引數到下一個頁面
action action
比如:this.props.navigation.navigate('Find', {param: 'i am the param'});

state

state裡面包含有傳遞過來的引數paramskey、路由名稱routeName,列印log可以看得到:

{ 
  params: { param: 'i am the param' },
  key: 'id-1500546317301-1',
  routeName: 'Mine' 
}複製程式碼
setParams

更改當前頁面路由的引數,比如可以用來更新頭部的按鈕或者標題。

componentDidMount() {
    this.props.navigation.setParams({param:'i am the new param'})
}複製程式碼
goBack

回退,可以不傳,也可以傳引數,還可以傳null

this.props.navigation.goBack();       // 回退到上一個頁面
this.props.navigation.goBack(null);   // 回退到任意一個頁面
this.props.navigation.goBack('Home'); // 回退到Home頁面複製程式碼

TabNavigator

TabNavigator,即是Tab選項卡,類似於原生android中的TabLayout,它的建構函式:

TabNavigator(RouteConfigs, TabNavigatorConfig)複製程式碼

api和StackNavigator類似,引數RouteConfigs是路由配置,引數TabNavigatorConfig是Tab選項卡配置。

RouteConfigs

路由配置和StackNavigator中是一樣的,配置路由以及對應的screen頁面,navigationOptions為對應路由頁面的配置選項:

  • title - Tab標題,可用作headerTitletabBarLabel回退標題
  • tabBarVisible - Tab的是否可見,沒有設定的話預設為true
  • tabBarIcon - Tab的icon元件,可以根據{focused: boolean, tintColor: string}方法來返回一個icon元件
  • tabBarLabel - Tab中顯示的標題字串或者元件,也可以根據{ focused: boolean, tintColor: string }方法返回一個元件
TabNavigatorConfig
  • tabBarComponent - Tab選項卡元件,有TabBarBottomTabBarTop兩個值,在iOS中預設為TabBarBottom,在Android中預設為TabBarTop
    • TabBarTop - 在頁面的頂部
    • TabBarBottom - 在頁面的底部
  • tabBarPosition - Tab選項卡的位置,有 topbottom兩個值
  • swipeEnabled - 是否可以滑動切換Tab選項卡
  • animationEnabled - 點選Tab選項卡切換介面是否需要動畫
  • lazy - 是否懶載入頁面
  • initialRouteName - 初始顯示的Tab對應的頁面路由名稱
  • order - 用路由名稱陣列來表示Tab選項卡的順序,預設為路由配置順序
  • paths - 路徑配置
  • backBehavior - androd點選返回鍵時的處理,有initialRoutenone兩個值
    • initailRoute - 返回初始介面
    • none - 退出
  • tabBarOptions - Tab配置屬性,用在TabBarTopTabBarBottom時有些屬性不一致:
    • 用於TabBarTop時:
      • activeTintColor - 選中的文字顏色
      • inactiveTintColor - 未選中的文字顏色
      • showIcon - 是否顯示圖示,預設顯示
      • showLabel - 是否顯示標籤,預設顯示
      • upperCaseLabel - 是否使用大寫字母,預設使用
      • pressColor - android 5.0以上的MD風格波紋顏色
      • pressOpacity - android 5.0以下或者iOS按下的透明度
      • scrollEnabled - 是否可以滾動
      • tabStyle - 單個Tab的樣式
      • indicatorStyle - 指示器的樣式
      • labelStyle - 標籤的樣式
      • iconStyle - icon的樣式
      • style - 整個TabBar的樣式
    • 用於TabBarBottom時:
      • activeTintColor - 選中Tab的文字顏色
      • activeBackgroundColor - 選中Tab的背景顏色
      • inactiveTintColor - 未選中Tab的的文字顏色
      • inactiveBackgroundColor - 未選中Tab的背景顏色
      • showLabel - 是否顯示標題,預設顯示
      • style - 整個TabBar的樣式
      • labelStyle - 標籤的樣式
      • tabStyle - 單個Tab的樣式
底部Tab導航示例
import React, {Component} from 'react';
import {StackNavigator, TabBarBottom, TabNavigator} from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
import TabBarItem from "./index18/TabBarItem";
export default class MainComponent extends Component {
    render() {
        return (
            <Navigator/>
        );
    }
}

const TabRouteConfigs = {
    Home: {
        screen: HomeScreen,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: '首頁',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_homepage_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_homepage_selected_2x.png')}
                />
            ),
        }),
    },
    NearBy: {
        screen: NearByScreen,
        navigationOptions: {
            tabBarLabel: '附近',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_merchant_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_merchant_selected_2x.png')}
                />
            ),
        },
    }
    ,
    Mine: {
        screen: MineScreen,
        navigationOptions: {
            tabBarLabel: '我的',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_mine_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_mine_selected_2x.png')}
                />
            ),
        },
    }
};
const TabNavigatorConfigs = {
    initialRouteName: 'Home',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    lazy: true,
};
const Tab = TabNavigator(TabRouteConfigs, TabNavigatorConfigs);
const StackRouteConfigs = {
    Tab: {
        screen: Tab,
    }
};
const StackNavigatorConfigs = {
    initialRouteName: 'Tab',
    navigationOptions: {
        title: '標題',
        headerStyle: {backgroundColor: '#5da8ff'},
        headerTitleStyle: {color: '#333333'},
    }
};
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);複製程式碼

頂部Tab選項卡示例
import React, {Component} from "react";
import {StackNavigator, TabBarTop, TabNavigator} from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
export default class MainComponent extends Component {
    render() {
        return (
            <Navigator/>
        );
    }
}

const TabRouteConfigs = {
    Home: {
        screen: HomeScreen,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: '首頁',
        }),
    },
    NearBy: {
        screen: NearByScreen,
        navigationOptions: {
            tabBarLabel: '附近',
        },
    }
    ,
    Mine: {
        screen: MineScreen,
        navigationOptions: {
            tabBarLabel: '我的',
        },
    }
};
const TabNavigatorConfigs = {
    initialRouteName: 'Home',
    tabBarComponent: TabBarTop,
    tabBarPosition: 'top',
    lazy: true,
    tabBarOptions: {}
};
const Tab = TabNavigator(TabRouteConfigs, TabNavigatorConfigs);
const StackRouteConfigs = {
    Tab: {
        screen: Tab,
    }
};
const StackNavigatorConfigs = {
    initialRouteName: 'Tab',
    navigationOptions: {
        title: '標題',
        headerStyle: {backgroundColor: '#5da8ff'},
        headerTitleStyle: {color: '#333333'},
    }
};
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);複製程式碼

DrawerNavigator

在原生Android MD 風格里面很多app都會採用側滑抽屜來做主頁面的導航,利用DrawerNavigator在RN中可以很方便來實現抽屜導航。

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)複製程式碼

DrawerNavigator的建構函式一樣,引數配置也類似。

RouteConfigs

抽屜導航的路由配置RouteConfigs,和TabNavigator的路由配置完全一樣,screen配置對應路由頁面,navigationOptions為對應頁面的抽屜配置選項:

  • title - 抽屜標題,和headerTitledrawerLabel一樣
  • drawerLabel - 標籤字串,或者自定義元件, 可以根據{ focused: boolean, tintColor: string }函式來返回一個自定義元件作為標籤
  • drawerIcon - 抽屜icon,可以根據{ focused: boolean, tintColor: string }函式來返回一個自定義元件作為icon
DrawerNavigatorConfig

抽屜配置項屬性:

  • drawerWidth - 抽屜寬度,可以使用Dimensions獲取螢幕的寬度,動態計算
  • drawerPosition - 抽屜位置,可以是left或者right
  • contentComponent - 抽屜內容元件,可以自定義側滑抽屜中的所有內容,預設為DrawerItems
  • contentOptions - 用來配置抽屜內容的屬性。當用來配置DrawerItems是配置屬性選項:
    • items - 抽屜欄目的路由名稱陣列,可以被修改
    • activeItemKey - 當前選中頁面的key id
    • activeTintColor - 選中條目狀態的文字顏色
    • activeBackgroundColor - 選中條目的背景色
    • inactiveTintColor - 未選中條目狀態的文字顏色
    • inactiveBackgroundColor - 未選中條目的背景色
    • onItemPress(route) - 條目按下時會呼叫此方法
    • style - 抽屜內容的樣式
    • labelStyle - 抽屜的條目標題/標籤樣式
  • initialRouteName - 初始化展示的頁面路由名稱
  • order - 抽屜導航欄目順序,用路由名稱陣列表示
  • paths - 路徑
  • backBehavior - androd點選返回鍵時的處理,有initialRoute和none兩個值,initailRoute:返回初始介面,none:退出
抽屜導航示例
import React, {Component} from 'react';
import {DrawerNavigator, StackNavigator, TabBarBottom, TabNavigator} from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
import TabBarItem from "./index18/TabBarItem";
export default class MainComponent extends Component {
    render() {
        return (
            <Navigator/>
        );
    }
}
const DrawerRouteConfigs = {
    Home: {
        screen: HomeScreen,
        navigationOptions: ({navigation}) => ({
            drawerLabel : '首頁',
            drawerIcon : ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_homepage_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_homepage_selected_2x.png')}
                />
            ),
        }),
    },
    NearBy: {
        screen: NearByScreen,
        navigationOptions: {
            drawerLabel : '附近',
            drawerIcon : ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_merchant_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_merchant_selected_2x.png')}
                />
            ),
        },
    },
    Mine: {
        screen: MineScreen,
        navigationOptions: {
            drawerLabel : '我的',
            drawerIcon : ({focused, tintColor}) => (
                <TabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    normalImage={require('./img/tabbar/pfb_tabbar_mine_2x.png')}
                    selectedImage={require('./img/tabbar/pfb_tabbar_mine_selected_2x.png')}
                />
            ),
        },
    }
};
const DrawerNavigatorConfigs = {
    initialRouteName: 'Home',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    lazy: true,
    tabBarOptions: {}
};
const Drawer = DrawerNavigator(DrawerRouteConfigs, DrawerNavigatorConfigs);
const StackRouteConfigs = {
    Drawer: {
        screen: Drawer,
    }
};
const StackNavigatorConfigs = {
    initialRouteName: 'Drawer',
    navigationOptions: {
        title: '標題',
        headerStyle: {backgroundColor: '#5da8ff'},
        headerTitleStyle: {color: '#333333'},
    }
};
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);複製程式碼


原始碼:git.oschina.net/xiaojianjun… (index20.js、index21.js、index22.js)

參考

reactnavigation.org/docs/
ReactNative導航新寵兒react-navigation

相關文章