react-navigation,刷新你的導航

在2017年1月,新開源的react-navigation庫備受矚目。它有類似于原生版性能的體驗效果,可能會成為未來RN導航組件中的主力軍。該庫包含三類組件:
(1)StackNavigator:用來跳轉頁面和傳遞參數。stack就是數據結構的堆棧技術,遵循后進先出的原理。
(2)TabNavigator:類似底部導航欄,用來在同一屏幕下切換不同界面
(3)DrawerNavigator:側滑菜單導航欄,用于輕松設置帶抽屜導航的屏幕

來朵花花

一、屬性介紹

1.1StackNavigator屬性

  • navigationOptions:用于配置StackNavigator的一些屬性。
    • title:標題,如果設置了該屬性,導航欄和標簽欄的title就會變成一樣。故不建議使用
    • header:設置一些導航的屬性,若想要隱藏頂部導航欄則只需要把這個屬性設置為null
    • headerTitle:設置導航欄標題
    • headerBackTitle:設置跳轉頁面左側返回箭頭后面的文字,默認是上一個頁面的標題,當然也可以自定義設置設置成null
    • headerTruncatedBackTitle:設置當上個頁面標題不符合返回箭頭后的文字時,默認改成"返回"
    • headerRight:設置導航條右側。可以是按鈕或者是其他視圖控件
    • headerLeft:設置導航條右側。可以是按鈕或者是其他視圖控件
    • headerStyle:設置導航條的樣式,背景色及寬高等
    • headerTitleStyle:設置導航欄文字樣式
    • headerBackTitleStyle:設置導航欄"返回"的文字樣式
    • headerTintColor:設置導航欄顏色
    • headerPressColorAndroid:安裝獨有的設置顏色紋理。當然只有在安卓5.0以上才有效果
    • gesturesEnabled:是否支持滑動返回手勢。iOS默認支持,安卓默認關閉
  • screen:對應界面名稱,需要填入import之后的頁面
  • mode:定義跳轉風格
    • card:使用iOS和安卓默認的風格。直接切換
    • modal:iOS獨有的使屏幕從底部拖出
  • headerMode:返回上級頁面時的動畫效果
    • float:iOS的默認效果
    • screen:滑動過程中,整個頁面都會返回
    • none:無動畫
  • cardStyle:自定義設置跳轉效果
    • transitionConfig:自定義設置滑動返回的配置
    • onTransitionStart:當轉換動畫即將被調用的功能
    • onTransitionEnd:當轉換動畫完成時被調用的功能
  • path:路由中設置的路徑的覆蓋映射配置。path用于聲明一個界面路徑
  • initialRouteName:設置默認的頁面組件,必須是已經注冊的頁面組件
  • initailRouteParams:設置路由參數

1.2TabNavigator屬性

  • screen:和導航的功能一樣,對應界面名稱,可以在氣頭頁面通過這個screen傳值和跳轉
  • navigationOptions:配置TabNavigator的一些屬性
  • title:標題,會同時設置導航條和標簽欄的title
  • tabBarVisible:是否顯示標簽欄。默認是true不隱藏
  • tabBarIcon:設置標簽欄的圖標。需要給每一項都設置
  • tabBarLabel:設置標簽欄的title

以下屬性配合導航使用

  • tabBarPosition:設置tabBar的位置,屬性值為top和bottom。iOS默認在底部,安卓默認在頂部

  • swipeEnabled:是否允許在標簽之間進行滑動

  • animationEnabled:是否在更改標簽時顯示動畫

  • lazy:是否在app打開的時候將底部的標簽欄全部加載,默認為flase。推薦打開

  • trueInitialRouteName:設置默認的頁面組件

  • backBehavior:按back鍵是否跳轉到第一個tab,none為不跳轉

  • tabBarOptions:設置標簽欄

  • 專屬iOS屬性

    • activeTintColor:設置在活躍狀態下,label和icon的前景色
    • activeBackgroundColor:label和icon的背景色
    • inactiveTintColor:設置在不活躍狀態下,label和icon的前景色
    • inactiveTintColor:設置在不活躍狀態下,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:圖標樣式

1.3DrawerNavigator屬性介紹

  • DrawerNavigatorConfig屬性
    • drawerWidth - 抽屜的寬度
    • drawerPosition - 選項是左或右。 默認為左側位置
    • contentComponent - 用于呈現抽屜內容的組件,例如導航項。 接收抽屜的導航。 默認為DrawerItems
    • contentOptions - 配置抽屜內容
    • initialRouteName - 初始路由的routeName
    • order - 定義抽屜項目順序的routeNames數組。
      路徑 - 提供routeName到路徑配置的映射,它覆蓋routeConfigs中設置的路徑。
    • backBehavior - 后退按鈕是否會切換到初始路由? 如果是,設置為initialRoute,否則為none。 默認為initialRoute行為
    • DrawerItems的contentOptions屬性
    • activeTintColor - 活動標簽的標簽和圖標顏色
    • activeBackgroundColor - 活動標簽的背景顏色
    • inactiveTintColor - 非活動標簽的標簽和圖標顏色
    • inactiveBackgroundColor - 非活動標簽的背景顏色
      內容部分的樣式樣式對象
    • labelStyle - 當您的標簽是字符串時,要覆蓋內容部分中的文本樣式的樣式對象

二、案例

2.1StackNavigation案例

  • 集成第三方庫
    使用npm安裝react-navigation庫,--save表示將該組件寫入到package.json文件中。
npm install react-navigation --save

當然,也可以采用yarn工具將該庫添加到項目中

 yarn add react-navigation
  • 導入組件到項目中

    本項目創建于0.49.2的環境中,這次RN對該版本做了重大改進。安卓端和iOS的文件混合成為index.js文件。而文件App.js注冊到了又注冊到了index.js文件。故我們將需要用到的代碼編寫在App.js文件中。

import {StackNavigator} from 'react-navigation';
  • 創建導航,并且添加路由
import HomeScreen from './HomeScreen'; //導入需要展示的頁面
const  Navigator = StackNavigator(
//設置導航要展示的頁面
    {
       HomeScreen:{screen:HomeScreen}   
    },
    //設置navigationOptions屬性對象
    {
      navigationOptions: {
        title: '標題', //在導航中顯示的標題內容
        headerBackTitle:null,
        headerTintColor:'#333333',
        showIcon:true,
        swipeEnabled:false,
        animationEnabled:false,
      },
      mode:'card',  //設置mode屬性
    }
);
  • 在render函數中返回導航
export default class App extends Component<{}> {
  render() {
    return (
       <Navigator/>
    );
  }
}
  • HomeScreen.js代碼實現
import React, { Component } from 'react';
import {
    Platform,
    StyleSheet,
    AppRegistry,
    Text,
    View
} from 'react-native';

export default class HomeScreen extends Component {
    render(){
        return(
            <View style={{flex:1,backgroundColor:'pink'}}>
                <Text>你好啊 在干嘛呢</Text>
            </View>
        );
    }
}
效果圖

下面可以來做導航的跳轉操作
為了實現跳轉操作的功能,需要先新建一個頁面,并且將這個頁面添加到導航中去。

  • 導入頁面到App.js文件
import ChatScreen from './ChatScreen'  //新建的文件
const  Navigator = StackNavigator(
    {
       HomeScreen:{screen:HomeScreen},
       ChatScreen:{screen:ChatScreen}  //這是新添加的導航界面
  • 跳轉操作

只要界面加入到了導航當中,組件中就會自動添加navigation的navigate屬性。使用該屬性可以跳轉到下一個界面。下面是HomeScreen中的代碼。ChatScreen是第二個導航界面。在HomeScreen中添加一個button組件,使用routeName路由名稱ChatScreen關聯到組件ChatScreen.

export default class HomeScreen extends Component {

    render(){
        return(
            <View style={{flex:1,backgroundColor:'pink'}}>
                <Text>你好啊 在干嘛呢</Text>
                <Button
                  onPress={()=>this.props.navigation.navigate('ChatScreen')}
                  title={"chat with lucy"}
                />
            </View>
        );
    }
}
  • 返回操作

當第二個界面想要回歸到上一個界面時,也要用到navigation的goBack屬性。當然導航有自身的返回按鈕。以下代碼是ChatScreen組件的代碼,當用戶組件Text也會返回到上一個界面。

export default class ChatScreen extends Component {
    static navigationOptions = {
        title: 'Chat with Lucy',
    };
    render() {
        return (
            <View>
                <Text onPress={()=>this.props.navigation.goBack()}>Chat with Lucy</Text>
            </View>
        );
    }
}
效果圖
  • 傳遞參數
    在ChatScreen頁面中,如果直接寫死標題則不利于代碼的可維護性。所以我們可以在導航的時候傳遞參數。首先編輯一下HomeScreen組件,傳遞自定義的屬性user參數到路由中去。
export default class HomeScreen extends Component {
    render(){
        const { navigate } = this.props.navigation;
        return(
            <View style={{flex:1,backgroundColor:'pink'}}>
                <Text>你好啊 在干嘛呢</Text>
                <Button
                  onPress={()=>navigate('ChatScreen',{user:'dudu'})}
                  title={"chat with lucy"}
                />
            </View>
        );
    }
}

之后可以編輯ChatScreen組件顯示的user參數,這個參數通過route來傳遞。為了代碼的健壯性,如果外界的user屬性有值,就將user賦值給title。如果沒有則讓title為空。
設置導航右邊的菜單,設置一個“返回”的文字

static navigationOptions =({ navigation, screenProps }) => ({
    title: navigation.state.params?navigation.state.params.user:null,
    headerRight:(
        <Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
            返回
        </Text>
    )
});
  • 外界傳值

我們也可以將外界的參數傳遞給函數內部。下面的代碼采用結構賦值的方法,取出導航中狀態機的參數params,取出參數中的user,一樣可以拿到外界參數。

 render() {
        const {params} = this.props.navigation.state;
        return (
            <View>
                <Text onPress={()=>this.props.navigation.goBack()}>Chat with {params.user}</Text>
            </View>
        );
    }
效果圖

2.2 TabNavigator案例

react-navigation組件除了可以用做頁面間的跳轉,當然也可以用做tab界面之間的切換。

  • 導入react-navigation的子組件。這些組件分別是用于界面切換、跳轉、和標簽欄外置的擺放。
import {StackNavigator,TabNavigator,TabBarBottom} from 'react-navigation';
  • 封裝一個TabBarItem,用于設置每個tab的圖片
import React,{Component} from 'react';
import {Image} from 'react-native';

export default class TabBarItem extends Component {

    render() {
        return(
            <Image source={ this.props.focused ? this.props.selectedImage : this.props.normalImage }
                   style={ { tintColor:this.props.tintColor,width:25,height:25 } }
            />
        )
    }

}
  • 導入封裝的TabBarItem組件 表示TabBar的每一項
import TabBarItem from './TabBarItem';
  • 定義TabNavigator。定義幾個要切換的tab,每個tab設置好對應要顯示的屏幕。當然,從之前介紹的屬性可知,TabNavigator也擁有navigationOptions屬性,它由系統傳入navigation參數,之后來設置其他的子屬性。比如說tabBarLabel設置每個tab的標題,tabBarIcon設置選中和非選中的圖片。
    之后再設置其它每個tab共同的屬性,用一個對象表示。
const Tab = TabNavigator({
  Home:{
    screen:HomeScreen,
    navigationOptions:({navigation}) => ({
      tabBarLabel:'首頁',
      tabBarIcon:({focused,tintColor}) => (
          <TabBarItem
              tintColor={tintColor}
              focused={focused}
              normalImage={require('./imgs/ic_like_sel.png') }
              selectedImage={require('./imgs/ic_mine_sel.png')}
          />
      )
    }),
  },

  Mine:{
    screen:MineScreen,
    navigationOptions:({navigation}) => ({
      tabBarLabel:'我',
      tabBarIcon:({focused,tintColor}) => (
          <TabBarItem
              tintColor={tintColor}
              focused={focused}
              normalImage={require('./imgs/ic_like_sel.png')}
              selectedImage={require('./imgs/ic_like_sel.png')}
          />
      )
    }),
  },
},

    {
      tabBarComponent:TabBarBottom,
      tabBarPosition:'bottom',
      swipeEnabled:false,
      animationEnabled:false,
      lazy:true,
      tabBarOptions:{
        activeTintColor:'#06c1ae',
        inactiveTintColor:'#979797',
        style:{backgroundColor:'#ffffff',},
        labelStyle: {
          fontSize: 20, // 文字大小
        },
      }
});
  • 將tab放入到Navigator中
const Navigator = StackNavigator(
    {
        Tab:{screen:Tab},

    },

    {
        navigationOptions:{
            // title:'首頁',
            headerBackTitle:null,
            headerTintColor:'#333333',
            showIcon:true,
            swipeEnabled:false,
            animationEnabled:false,
        },

        mode:'card',
    });
  • 在render方法中返回導航組件
export default class App extends Component<{}> {
  render() {
    return (
     <Navigator/>
    );
  }
}
  • HomePage和MinePage的代碼

StackNavigator還提供了onNavigationStateChange回調方法,用來監聽導航狀態的改變

import React, { Component } from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View
} from 'react-native';
export default class HomePage extends Component {

    static navigationOptions = {
        title:'首頁',
    };

    render() {
        return(
            <View style={{flex:1,backgroundColor:'yellow'}}>
                <Text onPress={this._skip.bind(this)}>點擊跳轉</Text>
            </View>
        );
    }

    _skip() {
        this.props.navigation.navigate("Mine");
    }
}
import React, { Component } from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View
} from 'react-native';
export default class MinePage extends Component {

    static navigationOptions = {
        title:'我',
    };

    render() {
        return(
            <View style={{flex:1,backgroundColor:'pink'}}>
                <Text onPress={this._skip.bind(this)}>MinePage</Text>
            </View>
        );
    }

    /**
     * 跳轉
     */
    _skip() {
        this.props.navigation.goBack();
    }
}
效果圖

2.3DreawerNavigator抽屜導航

DrawerNavigator是一個抽屜導航。設置方式其實跟設置Tab差不多。只是需要設定某些特殊的屬性。比如說drawerLabel、drawerIcon、drawerWidth、drawerPosition等等。

  • 定義抽屜導航
    HomeScreen與MineScree是導入外界的兩個界面,將它們定義到DrawerNavigator中。在抽屜導航中,將組件的屬性也一起設置好。
import {DrawerNavigator} from 'react-navigation';
import HomeScreen from './Pages/HomePage';
import MineScreen from './Pages/MinePage';

const MyApp = DrawerNavigator({
    Home: {
        screen: HomeScreen,
    },
    Mine: {
        screen:MineScreen,
    },
},
    {
        drawerWidth: 200, // 抽屜寬
        drawerPosition: 'left', // 抽屜在左邊還是右邊
        contentOptions: {
            initialRouteName: 'Home', // 默認頁面組件
            activeTintColor: 'white',  // 選中文字顏色
            activeBackgroundColor: '#ff8500', // 選中背景顏色
            inactiveTintColor: '#666',  // 未選中文字顏色
            inactiveBackgroundColor: '#fff', // 未選中背景顏色
            style: {  // 樣式

            }
        }
    }
);
  • 在render方法中返回抽屜組件
export default class App extends Component<{}> {
    // static navigationOptions={
    //     title:'app',
    //     gesturesEnabled:false,
    //     header:null,
    // }

    render() {
        return (
            <View style = {{flex:1,marginTop:20,}}>

                <MyApp />
            </View>
        );
    }
}
  • 設置HomePage子頁面的屬性
    一旦加入了導航組件react-navigation,那么其頁面就會有navigationOptions屬性。我們可以在這個屬性里面設置抽屜導航的樣式。
export default class HomePage extends Component<{}> {
    static navigationOptions = {
        drawerLabel: 'Home',
        drawerIcon: ({ tintColor }) => (
            <Image
                source={require('.././imgs/ic_like_sel.png')}
                style={[styles.icon, {tintColor: tintColor}]}
            />
        ),
    };
}
  • 返回HomePage頁面要展示的組件
    用navigation的navigate屬性可以跳轉到指定的頁面。如果指定的是DrawerOpen,意思就是打開抽屜。
render() {
        return (
            <View>
                <Button
                    onPress={() => this.props.navigation.navigate('Mine')}
                    title="Go to Mine"
                />
                <Button
                    onPress={()=>this.props.navigation.navigate('DrawerOpen')}
                    title="open the draw"
                />
            </View>
        );
    }
  • 設置樣式
const styles = StyleSheet.create({
    icon: {
        width: 24,
        height: 24,
    },
});
  • 設置MinePage頁面
    MinePage頁面和HomePage頁面相差不大。只是做代碼演示而已,這里不再闡述
import React, { Component } from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View,
    Image,
    Button
} from 'react-native';
export default class MineScreen extends Component<{}> {
    static navigationOptions = {
        drawerLabel: 'Mine',
        drawerIcon: ({ tintColor }) => (
            <Image
                source={require('.././imgs/ic_mine_sel.png')}
                style={[styles.icon, {tintColor: tintColor}]}
            />
        ),
    };

    render() {
        return (
            <View>
                <Button
                    onPress={() => this.props.navigation.goBack()}
                    title="Go back home"
                />

                <Button
                    onPress={()=>this.props.navigation.navigate('DrawerOpen')}
                    title="open the draw"
                />
            </View>
        );
    }
}
const styles = StyleSheet.create({
    icon: {
        width: 24,
        height: 24,
    },
});

效果圖如下:

效果圖

非寧靜無以致遠,非淡泊無以明志。在學習的道路上,多少會遇到泥濘挫折。我可以放慢腳步,但絕能不回頭,我的夢想,在路上。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,677評論 25 708
  • react-navigation導航組件使用詳解 注意了,如果有小伙伴們發現運行作者提供的react-naviga...
    光強_上海閱讀 23,490評論 38 103
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,777評論 1 92
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,155評論 4 61
  • 其實,要想成為有錢人其實很簡單:當你身邊都是有錢人的時候,你也一定會成為有錢人。 美國前總統克林頓原來是吹薩卡斯...
    她極美的靈魂閱讀 2,288評論 0 2