React Native03

此文項目代碼:https://github.com/bei-yang/I-want-to-be-an-architect
碼字不易,辛苦點個star,感謝!

引言


此篇文章主要涉及以下內容:

  • react navigation3.x的安裝流程
  • react navigation 相關屬性,和API
  • createStackNavigator普通導航使用
  • 使用react-native-vector-icons圖標庫

react navigation介紹

image.png

源于React Native社區對基于Javascript的可擴展且使用簡單的導航解決方案的需求

react-natvigation自開源以來。在短短不到3個月的時間,github上星數已達4000+。Fb推薦使用庫,并且在React Native當前最新版本0.44中將Navigator刪除。react-navigation據稱有原生般的性能體驗效果。可能會成為未來React Native導航組件的主流軍

安裝

https://reactnavigation.org/docs/zh-Hans/getting-started.html

導航器

導航器也可以看成是一個普通的React組件,你可以通過導航器來定義你的APP中的導航結構。導航器還可以渲染通用元素,例如可以配置的標題欄和選項卡欄。

在react-navigation中有以下類型的導航器:

  • createStackNavigator:類似普通的Navigator,導航上方導航欄
  • createTabNavigator:已棄用,使用createBottomTabNavigator、createMaterialTopTabNavigator替代
  • createBottomTabNavigator:相當于IOS里面的UITabBarController,屏幕下方的標簽欄
  • createMaterialTopTabNavigator:屏幕頂部的材料設計主題標簽欄
  • createDrawerNavigator:抽屜效果,側邊滑出
  • createSwitchNavigator:SwitchNavigator的用途是一次只顯示一個頁面

你可以通過以上幾種導航器來創建你的APP,可以是其中一個也可以多個組合,這個可以根據具體的應用場景并結合每一個導航器的特性進行選擇。

相關概念

在開始學習導航器之前,我們需要了解兩個和導航有關的概念:

  • Screen navigation prop(屏幕導航屬性):通過navigation可以完成屏幕之間的調度操作,例如打開另一個屏幕
  • Screen navigationOptions(屏幕導航選項):通過navigationOptions可以定制導航器顯示屏幕的方式(例如:頭部標題,選項卡標簽等)

導航器所支持的Props

const SomeNav = createStackNavigator/createBottomTabNavigator/createMaterialTopTabNavigator({
  // config
});
<SomeNav
    screenProps = {xxx} //向子屏幕傳遞額外的數據,子屏幕可以通過this.props.screenProps獲取到該數據
    ref = {nav => {navigation = nav;}} //可以通過ref屬性獲取到navigation;
    onNavigationStateChange=(prevState,newState,action)=>{
    //onNavigationStateChange:每次當導航器所管理的state發生改變時,都會回調該方法
    //prevState:變化之前的state
    //newState:新的state
    //action:導致state變化的action
    }
/>

Screen Navigation Prop(屏幕的navigation props)

當導航器中的屏幕被打開時,它會接收到一個navigation prop,它是整個導航環節的關鍵一員,接下來詳細的講解一下navigation prop的作用

navigation:包含以下功能

  • navigate:跳轉到其他界面
  • state:屏幕的當前state
  • setParams:改變路由的params
  • goBack:關閉當前屏幕
  • disPatch:向路由發送一個action
  • addListener:訂閱導航生命周期的更新
  • isFocused:true標識屏幕獲取了焦點
  • getParam:獲取具有回退的特定參數
  • dangerouslyGetParent:返回父導航器

注意:一個navigation有可能沒有navigate、setParams以及goBack,只有state與dispatch,所以在使用navigate時要進行判斷,如果沒有navigate可以使用navigation去dispatch一個新的action。如:

const {navigation,theme,selectedTab} = this.props;
const resetAction = StackActions.reset({
  index:0,
  action:[
    NavigationActions.navigate({
      routeName: 'HomePage',
      params:{
        theme:theme,
        selectedTab:selectedTab
      }
    })
  ]
})
navigation.dispatch(resetAction)

提示:這里的reset在2.0及以后的版本中,從NavigationActions中移到了StackActions中了,使用時記得留意。

StackNavigator的navigation的額外功能:

當且僅當當前navigator是stackNavigator時,this.props.navigation上有一些附加功能。這些函數是navigate和goBack的替代方法,你可以使用任何你喜歡的方法。這些功能是:

  • this.props.navigation
    • Push :導航到堆棧中的一個新路由
    • pop:返回堆棧中的上一個頁面
    • popToTop:跳轉到堆棧中最頂層的頁面
    • replace:用新路由替換當前路由
    • reset:擦除導航器狀態并將其替換為多個操作的結果
    • dismiss:關閉當前棧

使用navigate進行界面之間的跳轉

  • navigation.navigate({routeName,params,action,key})或者navigation.navigate(routeName,params,action)
    • routeName:要跳轉到的界面路由名稱,也就是導航其中配置的路由名
    • params:要傳遞給下一個界面的參數
    • action:如果該界面是一個navigator的話,將運行這個sub-action
    • Key:要導航到的路由的可選標識符,如果已存在,將后退到此路由
export const AppStackNavigator = createStackNavigator({
  HomeScreen: {
    screen: HomeScreen
  },
  Page1: {
    screen: Page1
  }
})

class HomeScreen extends React.Component {
  render(){
    const {navigate} = this.props.navigation;
    return (
        <View>
            <Text>This is HomeScreen</Text>
            <Button
                onPress={()=> navigate('Page1',{
            name: 'David'
                })}
                title = "Go to Page1"
            />
        </View>
    )
  }
}

使用state的params

可以通過this.props.state.params來獲取通過setParams(),或navigation.navigate()傳遞的參數。

<Button
    title={params.mode === 'edit' ? '保存' : '編輯'}
    onPress={()=>
        setParams({
      mode: params.mode === 'edit'? '' : 'edit'
        })
    }
/>
<Button
    title="Go to Page1"
    onPress={()=>{
    navigation.navigate('Page1',{name:'David'})
    }}
/>
const {navigation} = this.props
const {state,setParams} = navigation
const {params} = state
const showText = params.mode === 'edit'? '正在編輯':'編輯完成'

使用setParams改變route Params

  • setParams:function setParams(params):可以借助setParams來改變route Params,比如,通過setParams來更新頁面頂部的標題,返回按鈕等
class ProfileScreen extends React.Component {
  render(){
    const {setParams} = this.props.navigation
    return(
        <Button
            onPress={()=>setParams({name: 'Lucy'})}
            title="set title name to 'Lucy'"  
        />
    )
  }
}

注意navigation.setParams改變的是當前頁面的Params,如果要改變其他頁面的Params可以通過NavigationActions.setParams完成,下文會講到

使用goBack返回上一頁面或指定頁面

  • goBack:function goBack(key):我們可以借助goBack返回到上一頁或者路由棧的指定頁面。
    • 之中key標識你要返回到頁面的頁面標識符,如:id-1517035332238-4,不是routeName
    • 可以通過指定頁面的navigation.state.key來獲取頁面的標識
    • key非必傳,也可傳null

navigation.state {params: {…},key:"id-1517035332238-4",routeName:"Page1"}

export default class Page1 extends React.ComPonent {
  render(){
    const {navigation} = this.props;
    return <View>
        <Text>歡迎來到Page1</Text>
        <Button
            title="Go Back"
            onPress={()=>{
          navigation.goBack()
            }}
        />
    </View>
  }
}

通過dispatch 發送一個action

  • dispatch:function dispatch(action):給當前界面設置action,會替換原來的跳轉,回退等事件
const resetAction = StackActions.reset({
  index:0,
  actions:[
    NavigationActions.navigate({
      routeName: 'HomePage',
      params:{
        theme:theme,
        selectedTab:selectedTab
      }
    })
  ]
})
navigation.dispatch(resetAction)

NavigationActions

  • Navigate:導航到其他頁面
  • Back:返回到上一個頁面
  • Set Params:設置指定頁面的Params
  • Init:初始化一個state,如果state是undefined

Navigate

navigate action 會使用 navigate action的結果來更新當前的state

navigate({routeName,params,action,key})
  • routeName: 字符串,必選項,在app的router里注冊的導航目的地的routeName
  • params:對象,可選項,融合進目的地route的參數
  • actions:對象,可選項(高級),如果screen也是一個navigator,次級action可以在子route中運行,在文檔中描述的任何actions都可以作為次級action.
  • key:string or null 可選,要導航到的路由的標識符,如果已存在,則導航回此路由
import {NavigationActions} from 'react-navigation'
const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  params: {},
  action: NavigationActions.navigate({
    routeName: 'SubProfileRoute'
  })
})
this.props.navigation.dispatch(navigationAction)

Back

返回到前一個screen并且關閉當前screen.backaction creator 接受一個可選的參數:

back(key)

  • Key String可選,這個可以和上文中講到的goBack的key是一個概念;
import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back();
this.props.navigation.dispacth(backAction)

SetParams

通過SetParams我們可以修改指定頁面的Params

  • Params:對象,必選參數,將會被合并到已經存在頁面的Params中
  • key:字符串,必選參數,頁面的key
import {NavigationActions} from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
  params:{title:'HomePage'},
  key:'id-1517035332238-4'
})

有很多小伙伴可能會問:navigation中有setParams為什么還要有NavigationActions.setParams?

從兩方面來回答一下這個問題:

  • 在上文中講到過navigation中有可能只有stata和dispatch,這個時候如果要修改頁面的Params,則只能通過NavigationActions.setParams了
  • 另外,navigation.setParams只能修改當前頁面的params,而navigationActions.setParams可以修改所有頁面的Params

StackActions

  • Reset:重置當前state到一個新的state
  • replace:使用另一個路由替換指定的路由
  • Push:在堆棧頂部添加一個頁面,然后跳轉到該頁面
  • Pop:跳轉到上一個頁面
  • PopToTop:跳轉到堆棧最頂層的頁面,并銷毀其他所有頁面

Reset

Reset action刪掉所有的navigation state并且使用這個actions的結果來代替

  • index:數組,必選,navigation state中route數組中激活route的index
  • actions:數組,必選,navigation actions數組,將會替代navigation state
  • key:string or null 可選,如果設置,具有給定key的導航器將重置。如果為null,則根導航器將重置。

createStackNavigator-普通導航 堆棧

createStackNavigator提供APP屏幕之間切換的能力,它是以棧的形式還管理屏幕之間的切換,新切換到的屏幕會放在棧的頂部。

createStackNavigator API

createStackNavigator(RouteConfigs, StackNavigatorConfig):
  • RouteConfigs(必選):路由配置對象是從路由名稱到路由配置的映射,告訴導航器該路由呈現什么。
  • StackNavigatorConfig(可選):配置導航器的路由(如:默認首屏,navigationOptions,paths等)樣式(如,轉場模式mode、頭部模式等)。

RouteConfigs

RouteConfigs支持三個參數screenpath以及navigationOptions

  • screen(必選):指定一個 React 組件作為屏幕的主要顯示內容,當這個組件被createStackNavigator加載時,它會被分配一個navigation prop。
  • path(可選):用來設置支持schema跳轉時使用,具體使用會在下文的有關Schema章節中講到;
  • navigationOptions(可選):用以配置全局的屏幕導航選項如:title、headerRight、headerLeft等;

StackNavigatorConfig

react-navigation源碼中可以看出StackNavigatorConfig支持配置的參數有10個。

function createStackNavigator(routeConfigMap, stackConfig = {}) {
  const {
    initialRouteKey,
    initialRouteName,
    initialRouteParams,
    paths,
    defaultNavigationOptions,
    disableKeyboardHandling,
    getCustomActionCreators
  } = stackConfig;
  ...

這7個參數可以根據作用不同分為路由配置、視圖樣式配置兩類,首先看用于路由配置的參數:

用于路由配置的參數:

  • initialRouteName: 設置默認的頁面組件,必須是上面已注冊的頁面組件。
  • initialRouteParams: 初始路由的參數。
  • defaultNavigationOptions: 屏幕導航的默認選項,下文會詳細講解。
  • initialRouteKey - 初始路由的可選標識符。
  • paths: 用來設置支持schema跳轉時使用,具體使用會在下文的有關Schema章節中講到。

用于導航樣式配置的參數:

  • mode: 頁面切換模式: 左右是card(相當于iOS中的push效果), 上下是modal(相當于iOS中的modal效果)
    • card: 普通app常用的左右切換。
    • modal: 上下切換。
  • headerMode: 導航欄的顯示模式: screen: 有漸變透明效果, float: 無透明效果, none: 隱藏導航欄。
    • float: 無透明效果, 默認。
    • screen: 有漸變透明效果, 如微信QQ的一樣。
    • none: 隱藏導航欄。
  • headerBackTitleVisible : 提供合理的默認值以確定后退按鈕標題是否可見,但如果要覆蓋它,則可以使用true或` false 在此選項中。
    • fade-in-place: 標題組件交叉淡入淡出而不移動,類似于iOS的Twitter,Instagram和Facebook應用程序。 這是默認值。
    • uikit: iOS的默認行為的近似值。 headerTransitionPreset: 指定在啟用headerMode:float時header應如何從一個屏幕轉換到另一個屏幕。
  • cardStyle: 樣式(iOS上頁面切換會有白色漸變蒙層,想去掉則可以這樣設置,cardStyle: { opacity: null },切換頁面時的頁面邊框也在這里可以設置)。
  • onTransitionStart: 頁面切換開始時的回調函數 (我們可以在這里注冊一些通知,告知我們切面切換的狀態,方便后面處理頁面切換事件)。
  • onTransitionEnd: 頁面切換結束時的回調函數。

navigationOptions(屏幕導航選項)

支持一下參數:

  • title: 可以作為headerTitle的備選字段(當沒設置headerTitle時會用該字段作為標題),也可以作為TabNavigator的tabBarLabel以及DrawerNavigator的drawerLabel。
  • header: 自定義導航條,可以通過設置null來隱藏導航條;
  • headerTitle: 標題;
  • headerTitleAllowFontScaling: 標題是否允許縮放,默認true;
  • headerBackTitle: 定義在iOS上當前頁面進入到下一頁面的回退標題,可以通過設置null來禁用它;
  • headerTruncatedBackTitle: 當回退標題不能顯示的時候顯示此屬性的標題,比如回退標題太長了;
  • headerBackImage:React 元素或組件在標題的后退按鈕中顯示自定義圖片。 當組件被調用時,它會在渲染時收到許多 props 如:(tintColor,title)。 默認為帶有 react-navigation/views/assets/back-icon.png 這張圖片的組件,后者是平臺的默認后圖標圖像(iOS上為向左的符號,Android上為箭頭)。
  • headerRight: 定義導航欄右邊視圖;
  • headerLeft: 定義導航欄左邊視圖;
  • headerStyle: 定義導航欄的樣式,比如背景色等;
  • headerTitleStyle: 定義標題的樣式;
  • headerLeftContainerStyle:自定義 headerLeft 組件容器的樣式,例如,增加 padding。
  • headerRightContainerStyle:自定義 headerRight 組件容器的樣式,,例如,增加 padding。
  • headerTitleContainerStyle:自定義 headerTitle 組件容器的樣式, 例如,增加 padding。
  • headerBackTitleStyle: 定義返回標題的樣式;
  • headerPressColorAndroid:顏色為材料波紋 (Android >= 5.0);
  • headerTintColor: 定義導航條的tintColor,會覆蓋headerTitleStyle中的顏色;
  • headerTransparent:默認為 false。如果 true, 則標頭將不會有背景, 除非您顯式提供 headerStyle 或 headerBackground。
  • headerBackground:與headerTransparent一起使用,以提供在標題后臺呈現的組件。 例如,您可以使用模糊視圖來創建半透明標題。
  • gesturesEnabled: 定義是否能側滑返回,iOS默認true,Android默認false;
  • gestureResponseDistance: 定義滑動返回的有效距離,水平狀態下默認:25,垂直狀態默認135;
  • gestureDirection: 設置關閉手勢的方向。默認從左向右,可以設置從右到左的滑動操作。

創建一個StackNavigator類型的導航器

export const AppStackNavigator = createStackNavigator({
    HomePage: {
        screen: HomePage
    },
    Page1: {
        screen: Page1,
        navigationOptions: ({navigation}) => ({
            title: `${navigation.state.params.name}頁面名`//動態設置navigationOptions
        })
    },
    Page2: {
        screen: Page2,
        navigationOptions: {//在這里定義每個頁面的導航屬性,靜態配置
            title: "This is Page2.",
        }
    },
    Page3: {
        screen: Page3,
        navigationOptions: (props) => {//在這里定義每個頁面的導航屬性,動態配置
            const {navigation} = props;
            const {state, setParams} = navigation;
            const {params} = state;
            return {
                title: params.title ? params.title : 'This is Page3',
                headerRight: (
                    <Button
                        title={params.mode === 'edit' ? '保存' : '編輯'}
                        onPress={() =>
                            setParams({mode: params.mode === 'edit' ? '' : 'edit'})}
                    />
                ),
            }
        }
    },
}, {
    defaultNavigationOptions: {
        // header: null,// 可以通過將header設為null 來禁用StackNavigator的Navigation Bar
    }
});

配置navigationOptions:

步驟一的代碼中通過兩種方式配值了navigationOptions:

靜態配置:

對Page2的navigationOptions配置是通過靜態配置完成的:

Page2: {
    screen: Page2,
    navigationOptions: {//在這里定義每個頁面的導航屬性,靜態配置
        title: "This is Page2.",
    }
},

這種方式被稱為靜態配置,因為navigationOptions中的參數是直接Hard Code的不依賴于變量。

動態配置:

對Page3的navigationOptions配置是通過動態配置完成的:

Page3: {
    screen: Page3,
    navigationOptions: (props) => {//在這里定義每個頁面的導航屬性,動態配置
        const {navigation} = props;
        const {state, setParams} = navigation;
        const {params} = state;
        return {
            title: params.title ? params.title : 'This is Page3',
            headerRight: (
                <Button
                    title={params.mode === 'edit' ? '保存' : '編輯'}
                    onPress={() =>
                        setParams({mode: params.mode === 'edit' ? '' : 'edit'})}
                />
            ),
        }
    }
},

從上述代碼中可以看出Page3的navigationOptions依賴于props這個變量所以是動態的,當props中的內容發生變化時,navigationOptions也會跟著變化;

提示:除了在創建createStackNavigator時配置navigationOptions外,在StackNavigator之外也可以配置navigationOptions;

createStackNavigator之外也可以配置navigationOptions

方式一:

Page2.navigationOptions = {
     title: "This is Page2.",
};

方式二:

export default class Page1 extends React.Component {
    //也可在這里定義每個頁面的導航屬性,這里的定義會覆蓋掉別處的定義
    static navigationOptions = {
        title: 'Page1',
    };
    ...

第三步:界面跳轉

export default class HomePage extends React.Component {
    //在這里定義每個頁面的導航屬性
    static navigationOptions = {
        title: 'Home',
        headerBackTitle:'返回哈哈',//設置返回此頁面的返回按鈕文案,有長度限制
    }

    render() {
        const {navigation} = this.props;
        return <View style=>
            <Text style={styles.text}>歡迎來到HomePage</Text>
            <Button
                title="Go To Page1"
                onPress={() => {
                    navigation.navigate('Page1', {name: '動態的'});
                }}
            />
            <Button
                title="Go To Page2"
                onPress={() => {
                    navigation.navigate('Page2');
                }}
            />
            <Button
                title="Go To Page3"
                onPress={() => {
                    navigation.navigate('Page3',{ name: 'Devio' });
                }}
            />
        </View>
    }
}

代碼解析:

頁面跳轉可分為兩步:

    1. 獲取navigation:
      const {navigation} = this.props;
    
    1. 通過navigate(routeName, params, action)進行頁面跳轉:
       navigation.navigate('Page2');
       navigation.navigate('Page3',{ name: 'Devio' });
    

    這里在跳轉到Page3的時候傳遞了參數{ name: 'Devio' }

第四步:更新頁面Params與返回

export default class Page3 extends React.Component {
    render() {
        const {navigation} = this.props;
        const {state, setParams} = navigation;
        const {params} = state;
        const showText = params.mode === 'edit' ? '正在編輯' : '編輯完成';
        return <View style=>
            <Text style={styles.text}>歡迎來到Page3</Text>
            <Text style={styles.showText}>{showText}</Text>
            <TextInput
                style={styles.input}
                onChangeText={text=>{
                    setParams({title:text})
                }}
            />
            <Button
                title="Go Back"
                onPress={() => {
                    navigation.goBack();
                }}
            />
        </View>
    }
}

代碼解析:

在上述代碼中通過:

 <TextInput
    style={styles.input}
    onChangeText={text=>{
        setParams({title:text})
    }}
/>

將輸入框中內容的變化,通過setParams({title:text})更新到頁面的標題上,你會看到當輸入框中內容發生變化時,標題也會跟著變。

當用戶單擊Go Back按鈕時,通過:

navigation.goBack();

實現了返回上一頁;

createBottomTabNavigator-底部導航

相當于iOS里面的TabBarController

createBottomTabNavigator API

createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig):
  • RouteConfigs(必選):路由配置對象是從路由名稱到路由配置的映射,告訴導航器該路由呈現什么。
  • BottomTabNavigatorConfig(可選):配置導航器的路由(如:默認首屏,navigationOptions,paths等)樣式(如,轉場模式mode、頭部模式等)。

從createBottomTabNavigator API上可以看出createBottomTabNavigator支持通過RouteConfigsBottomTabNavigatorConfig兩個參數來創建createBottomTabNavigator導航器。

RouteConfigs

RouteConfigs支持三個參數screenpath以及navigationOptions

  • screen(必選):指定一個 React 組件作為屏幕的主要顯示內容,當這個組件被TabNavigator加載時,它會被分配一個navigation prop。
  • path(可選):用來設置支持schema跳轉時使用,具體使用會在下文的有關Schema章節中講到;
  • navigationOptions(可選):用以配置全局的屏幕導航選項如:title、headerRight、headerLeft等;

BottomTabNavigatorConfig

  • tabBarComponent:指定createBottomTabNavigator的TabBar組件,如果不指定在iOS上默認使用TabBarBottom,在Android平臺上默認使用TabBarTop。
    • TabBarBottomTabBarTop都是react-navigation所支持的組件,要自定義TabBar可以重寫這兩個組件也可以根據需要自己實現一個;
  • tabBarOptions: 配置TaBar下文會詳細講解;
  • initialRouteName : 默認頁面組件,createBottomTabNavigator顯示的第一個頁面;
  • order: 定義tab順序的routeNames數組。
  • paths: 提供routeName到path config的映射,它覆蓋routeConfigs中設置的路徑。
  • backBehavior: 后退按鈕是否會導致標簽切換到初始tab? 如果是,則設切換到初始tab,否則什么也不做。 默認為切換到初始tab。

tabBarOptions(tab配置)

  • activeTintColor: 設置TabBar選中狀態下的標簽和圖標的顏色;
  • inactiveTintColor: 設置TabBar非選中狀態下的標簽和圖標的顏色;
  • showIcon: 是否展示圖標,默認是false;
  • showLabel: 是否展示標簽,默認是true;
  • upperCaseLabel - 是否使標簽大寫,默認為true。
  • tabStyle: 設置單個tab的樣式;
  • indicatorStyle: 設置 indicator(tab下面的那條線)的樣式;
  • labelStyle: 設置TabBar標簽的樣式;
  • iconStyle: 設置圖標的樣式;
  • style: 設置整個TabBar的樣式;
  • allowFontScaling: 設置TabBar標簽是否支持縮放,默認支持;
  • safeAreaInset:覆蓋的forceInset prop,默認是{ bottom: 'always', top: 'never' },可選值:top | bottom | left | right ('always' | 'never');

navigationOptions(屏幕導航選項)

createBottomTabNavigator支持的屏幕導航選項的參數有:

  • title: 可以用作headerTitle和tabBarLabel的備選的通用標題。
  • tabBarVisible: 顯示或隱藏TabBar,默認顯示;
  • tabBarIcon: 設置TabBar的圖標;
  • tabBarLabel: 設置TabBar的標簽;
  • tabBarOnPress: Tab被點擊的回調函數,它的參數是一保函一下變量的對象:
    • navigation: navigation prop ;
    • defaultHandler: tab按下的默認處理程序;
  • tabBarButtonComponent:React組件,它包裝圖標和標簽并實現onPress。 默認情況下是TouchableWithoutFeedback的一個封裝,使其其表現與其它可點擊組件相同,tabBarButtonComponent: TouchableOpacity 將使用 TouchableOpacity 來替代;
  • tabBarAccessibilityLabel:選項卡按鈕的輔助功能標簽。 當用戶點擊標簽時,屏幕閱讀器會讀取這些信息。 如果您沒有選項卡的標簽,建議設置此項;
  • tabBarTestID:用于在測試中找到該選項卡按鈕的 ID;

案例

export const AppTabNavigator = createBottomTabNavigator({
    Page1: {
        screen: Page1,
        navigationOptions: {
            tabBarLabel: 'Page1',
            tabBarIcon: ({tintColor, focused}) => (
                <Ionicons
                    name={focused ? 'ios-home' : 'ios-home-outline'}
                    size={26}
                    style=
                />
            ),
        }
    },
    Page2: {
        screen: Page2,
        navigationOptions: {
            tabBarLabel: 'Page2',
            tabBarIcon: ({tintColor, focused}) => (
                <Ionicons
                    name={focused ? 'ios-people' : 'ios-people-outline'}
                    size={26}
                    style=
                />
            ),
        }
    },
    Page3: {
        screen: Page3,
        navigationOptions: {
            tabBarLabel: 'Page3',
            tabBarIcon: ({tintColor, focused}) => (
                <Ionicons
                    name={focused ? 'ios-chatboxes' : 'ios-chatboxes-outline'}
                    size={26}
                    style=
                />
            ),
        }
    },
}, {
    tabBarComponent: TabBarComponent,
    tabBarOptions: {
        activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff',
    }
});

在上述代碼中使用了react-native-vector-icons的矢量圖標作為Tab的顯示圖標,tabBarIcon接收一個React 組件,大家可以根據需要進行定制:

  • tintColor: 當前狀態下Tab的顏色;
  • focused: Tab是否被選中;

react-native-vector-icons

安裝

yarn add react-native-vector-icons

react-native link react-native-vector-icons

圖標庫地址:

https://oblador.github.io/react-native-vector-icons/

createMaterialTopTabNavigator-頂部導航

createMaterialTopTabNavigator API

createMaterialTopTabNavigator(RouteConfigs, TabNavigatorConfig):
  • RouteConfigs(必選):路由配置對象是從路由名稱到路由配置的映射,告訴導航器該路由呈現什么。
  • TabNavigatorConfig(可選):配置導航器的路由(如:默認首屏,navigationOptions,paths等)樣式(如,轉場模式mode、頭部模式等)。

從createMaterialTopTabNavigator API上可以看出createMaterialTopTabNavigator支持通過RouteConfigsTabNavigatorConfig兩個參數來創建createMaterialTopTabNavigator導航器。

RouteConfigs

RouteConfigs支持三個參數screenpath以及navigationOptions

  • screen(必選):指定一個 React 組件作為屏幕的主要顯示內容,當這個組件被TabNavigator加載時,它會被分配一個navigation prop。
  • path(可選):用來設置支持schema跳轉時使用,具體使用會在下文的有關Schema章節中講到;
  • navigationOptions(可選):用以配置全局的屏幕導航選項如:title、headerRight、headerLeft等;

TabNavigatorConfig

  • tabBarComponent:指定TabNavigator的TabBar組件;
  • tabBarPosition: 用于指定TabBar的顯示位置,支持’top’ 與 ‘bottom’兩種方式;
  • swipeEnabled : 是否可以左右滑動切換tab;
  • lazy - 默認值是 false。如果是true,Tab 頁只會在被選中或滑動到該頁時被渲染。當為 false 時,所有的 Tab 頁都將直接被渲染;(可以輕松實現多Tab 頁面的懶加載);
  • optimizationsEnabled -是否將 Tab 頁嵌套在到 中。如果是,一旦該 Tab 頁失去焦點,將被移出當前頁面, 從而提高內存使用率。
  • animationEnabled : 切換頁面時是否有動畫效果。
  • initialLayout : 包含初始高度和寬度的可選對象可以被傳遞以防止react-native-tab-view呈現中的一個幀延遲;
  • tabBarOptions: 配置TaBar下文會詳細講解;
  • initialRouteName : 默認頁面組件,TabNavigator顯示的第一個頁面;
  • order: 定義tab順序的routeNames數組。
  • paths: 提供routeName到path config的映射,它覆蓋routeConfigs中設置的路徑。
  • backBehavior: 后退按鈕是否會導致標簽切換到初始tab? 如果是,則設切換到初始tab,否則什么也不做。 默認為切換到初始tab。

tabBarOptions(tab配置)

  • activeTintColor: 設置TabBar選中狀態下的標簽和圖標的顏色;
  • inactiveTintColor: 設置TabBar非選中狀態下的標簽和圖標的顏色;
  • showIcon: 是否展示圖標,默認是false;
  • showLabel: 是否展示標簽,默認是true;
  • upperCaseLabel - 是否使標簽大寫,默認為true。
  • tabStyle: 設置單個tab的樣式;
  • indicatorStyle: 設置 indicator(tab下面的那條線)的樣式;
  • labelStyle: 設置TabBar標簽的樣式;
  • iconStyle: 設置圖標的樣式;
  • style: 設置整個TabBar的樣式;
  • allowFontScaling: 設置TabBar標簽是否支持縮放,默認支持;
  • pressColor -Color for material ripple(僅支持 Android >= 5.0;
  • pressOpacity -按下標簽時的不透明度(支持 iOS 和 Android < 5.0);
  • scrollEnabled -是否支持 選項卡滾動

navigationOptions(屏幕導航選項)

createMaterialTopTabNavigator支持的屏幕導航選項的參數有:

  • title: 可以用作headerTitle和tabBarLabel的備選的通用標題。
  • swipeEnabled:是否允許tab之間的滑動切換,默認允許;
  • tabBarIcon: 設置TabBar的圖標;
  • tabBarLabel: 設置TabBar的標簽;
  • tabBarOnPress: Tab被點擊的回調函數,它的參數是一保函一下變量的對象:
    • navigation:頁面的 navigation props
    • defaultHandler: tab press 的默認 handler
  • tabBarAccessibilityLabel:選項卡按鈕的輔助功能標簽。 當用戶點擊標簽時,屏幕閱讀器會讀取這些信息。 如果您沒有選項卡的標簽,建議設置此項;
  • tabBarTestID:用于在測試中找到該選項卡按鈕的 ID;

createDrawerNavigator-抽屜導航

createDrawerNavigator API

createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig):
  • RouteConfigs(必選):路由配置對象是從路由名稱到路由配置的映射,告訴導航器該路由呈現什么。
  • DrawerNavigatorConfig(可選):配置導航器的路由(如:默認首屏,navigationOptions,paths等)樣式(如,轉場模式mode、頭部模式等)。

從createDrawerNavigator API上可以看出createDrawerNavigator支持通過RouteConfigsDrawerNavigatorConfig兩個參數來創建createDrawerNavigator導航器。

RouteConfigs

RouteConfigs支持三個參數screenpath以及navigationOptions

  • screen(必選):指定一個 React 組件作為屏幕的主要顯示內容,當這個組件被DrawerNavigator加載時,它會被分配一個navigation prop。
  • path(可選):用來設置支持schema跳轉時使用,具體使用會在下文的有關Schema章節中講到;
  • navigationOptions(可選):用以配置全局的屏幕導航選項如:title、headerRight、headerLeft等;

DrawerNavigatorConfig

  • drawerWidth: 設置側邊菜單的寬度;
  • drawerPosition: 設置側邊菜單的位置,支持’left’、 ‘right’,默認是’left’;
  • contentComponent: 用于呈現抽屜導航器內容的組件,例如導航項。接收抽屜導航器的 navigation 屬性 。默認為DrawerItems。有關詳細信息,請參閱下文;
  • contentOptions: 配置抽屜導航器內容,見下文;
  • useNativeAnimations: 是否啟用Native動畫,默認啟用;
  • drawerBackgroundColor: 側邊菜單的背景;
  • initialRouteName: 初始化哪個界面為根界面,如果不配置,默認使用RouteConfigs中的第一個頁面當做根界面;
  • order: drawer排序,默認使用配置路由的順序;
  • paths: 提供routeName到path config的映射,它覆蓋routeConfigs中設置的路徑。
  • backBehavior: 后退按鈕是否會導致標簽切換到初始drawer? 如果是,則設切換到初始drawer,否則什么也不做。 默認為切換到初始drawer。
import React,{Component} from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';

import { createDrawerNavigator } from 'react-navigation';

import Ionicons from 'react-native-vector-icons/Ionicons';


const HomeScreen=({navigation})=>(
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
            <Text>HomeScreen</Text>
            <Button
                 onPress={()=>(navigation.toggleDrawer())} 
                 title="Open Drawer"
            ></Button>
        </View>
    );

const ProfileScreen=()=>(
        <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}><Text>ProfileScreen</Text></View>
    );

const RootDrawer =createDrawerNavigator({
    Home:{
        screen:HomeScreen,
        navigationOptions:{
            drawerLabel:'MyHome',
            drawerIcon:({tintColor, focused })=>(
                <Ionicons                   
                      name={'ios-home'}
                      size={20}
                      style={{ color: tintColor }}
                ></Ionicons>
                ),
        },
    },
    Profile:{
        screen:ProfileScreen,
        navigationOptions:{
            drawerLabel:'MyProfile',
            drawerIcon:({tintColor})=>(
                <Ionicons 
                    name={'ios-person'}
                    size={20}
                    style={{color:tintColor}}
                ></Ionicons>
                ),
        },
    }
});

export default RootDrawer;

自定義側邊欄(contentComponent)

DrawerNavigator有個默認的帶滾動的側邊欄,你也可以通過重寫這個側邊欄組件來自定義側邊欄:

contentComponent:(props) => (
    <ScrollView style=>
        <SafeAreaView forceInset=>
            <DrawerItems {...props} />
        </SafeAreaView>
    </ScrollView>
)

DrawerItems的contentOptions

contentOptions主要配置側滑欄item的屬性,只對DrawerItems,例如我們剛才寫的例子,就可以通過這個屬性來配置顏色,背景色等。其主要屬性有:

  • items: 路由數組,如果要修改路由可以可以修改或覆蓋它;
  • activeItemKey: 定義當前選中的頁面的key;
  • activeTintColor: 選中item狀態的文字顏色;
  • activeBackgroundColor: 選中item的背景色;
  • inactiveTintColor: 未選中item狀態的文字顏色;
  • inactiveBackgroundColor: 未選中item的背景色;
  • onItemPress: 選中item的回調,這個參數屬性為函數,會將當前路由回調過去;
  • itemsContainerStyle: 定義itemitem容器的樣式;
  • itemStyle: 定義item的樣式;
  • labelStyle: 定義item文字的樣式;
  • iconContainerStyle: 定義item圖標容器的樣式;
  • activeLabelStyle:選中狀態下文本樣式;
  • inactiveLabelStyle:非選中狀態下文本樣式;
  • iconContainerStyle :用于設置圖標容器的樣式。

eg:

contentOptions: {
  activeTintColor: '#e91e63',
  itemsContainerStyle: {
    marginVertical: 0,
  },
  iconContainerStyle: {
    opacity: 1
  }
}

navigationOptions(屏幕導航選項)

DrawerNavigator支持的屏幕導航選項的參數有:

  • title: 可以用作headerTitle和drawerLabel的備選的通用標題。

  • drawerLabel:側滑標題;

  • drawerIcon:側滑的標題圖標,這里會回傳兩個參數:

    • {focused: boolean, tintColor: string}
      
      • focused: 表示是否是選中狀態;
      • tintColor: 表示選中的顏色;
  • drawerLockMode:指定抽屜的鎖定模式。 這也可以通過在頂級路由器上使用screenProps.drawerLockMode 動態更新。

側邊欄操作(打開、關閉、切換)

側邊欄支持以下幾種操作方式:

navigation.openDrawer();
navigation.closeDrawer();
navigation.toggleDrawer();
//或
navigation.dispatch(DrawerActions.openDrawer());
navigation.dispatch(DrawerActions.closeDrawer());
navigation.dispatch(DrawerActions.toggleDrawer());

其中路由名openDrawer對應這打開側邊欄的操作,DrawerClose對應關閉側邊欄的操作,toggleDrawer對應切換側邊欄操作,要進行這些操作我么還需要一個navigationnavigation可以從props中獲取;

  • 打開側邊欄:navigation.openDrawer();
  • 關閉側邊欄:navigation.closeDrawer();
  • 切換側邊欄:navigation.toggleDrawer();

createSwitchNavigator-開關導航

SwitchNavigator 的用途是一次只顯示一個頁面。 默認情況下,它不處理返回操作,并在你切換時將路由重置為默認狀態。

createSwitchNavigator API

createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig):
  • RouteConfigs(必選,同createStackNavigator的RouteConfigs):路由配置對象是從路由名稱到路由配置的映射,告訴導航器該路由呈現什么。
  • SwitchNavigatorConfig(可選):配置導航器的路由;

SwitchNavigatorConfig

幾個被傳遞到底層路由以修改導航邏輯的選項:

  • initialRouteName -第一次加載時初始選項卡路由的 routeName。
  • resetOnBlur - 切換離開屏幕時,重置所有嵌套導航器的狀態。 默認為true。
  • paths - 提供 routeName 到 path 配置的映射, 它重寫 routeConfigs 中設置的路徑。
  • backBehavior - 控制 “返回” 按鈕是否會導致 Tab 頁切換到初始 Tab 頁? 如果是, 設置為 initialRoute, 否則 none。 默認為none行為。
const AppStack = createStackNavigator({
    Home: {
        screen: HomePage
    },
    Page1: {
        screen: Page1
    }
});
const AuthStack = createStackNavigator({
    Login: {
        screen: Login
    },
},{
    navigationOptions: {
        // header: null,// 可以通過將header設為null 來禁用StackNavigator的Navigation Bar
    }
});

export default createSwitchNavigator(
    {
        Auth: AuthStack,
        App: AppStack,
    },
    {
        initialRouteName: 'Auth',
    }
);

你的贊是我前進的動力

求贊,求評論,求分享...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容