以下內(nèi)容參照StackNavigator官網(wǎng)文檔 鏈接
Hello React Navigation
- 參照官網(wǎng),如果要支持安卓架忌,要先下載react-navigation這個庫,在工程路徑下執(zhí)行:
npm install --save react-navigation
// 如果安裝了yarn 也可以使用以下命令
yarn add react-navigation
React Navigation中用到了StackNavigator我衬,即創(chuàng)建了一個類似于瀏覽器的歷史棧的對象叹放。StackNavigator和web歷史棧的一個關鍵區(qū)別是可以手勢和動畫效果。
創(chuàng)建基本導航棧
import React from 'react';
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
export default StackNavigator({
Home: { // 這個名字任意
screen: HomeScreen, // 必須有screen這個組件
},
});
因為StackNavigator()返回一個組件挠羔,所以可以直接通過export導出井仰。顯示這個棧中的內(nèi)容更,目前只有一個空的導航破加,和中間的文字俱恶。
在ReactNative中,在App.js中export的組件是整個App的入口(或者叫根組件),通常不會直接導出一個'導航棧'組件速那,而是用另外一個組件渲染'導航棧'組件。修改如下:
const RootStack = StackNavigator({
Home: {
screen: HomeScreen,
},
});
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
- 添加第二屏
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
}
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
第一個參數(shù)尿背,表示導航棧內(nèi)有哪些視圖;第二個是配置參數(shù)(可選)
修改initialRouteName后面的名稱端仰,可以發(fā)現(xiàn)初始化的頁面不同。
下節(jié)討論如何在雙屏間切換田藐。
雙屏間切換
- 在主屏設置Button荔烧,并添加點擊,關聯(lián)到this.props.navigation.navigate('Details')
import React from 'react';
import { Button, View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
this.props.navigation,這個屬性會被設置到所有StackNavigator中的頁面
navigate('Details'),將頁面名稱傳入該方法汽久,可以跳轉(zhuǎn)到指定頁面
只能跳轉(zhuǎn)到StackNavigator中的界面鹤竭,如果該名稱傳入錯誤,什么也不會發(fā)生景醇。
如果在Details頁面再添加一個Button跳轉(zhuǎn)到Details頁面臀稚,頁面會一直被添加。
- StackNavigator會在非首屏提供一個返回箭頭三痰,提供返回操作吧寺。也可以通過添加按鈕關聯(lián)goback返回。此外散劫,StackNavigator自動關聯(lián)了安卓的返回鍵稚机,點擊設備的返回鍵也可以返回。
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title = 'GO TO DETAIL AGAIN'
onPress = {()=>this.props.navigation.navigate('Details')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
測試發(fā)現(xiàn)获搏,自己設置返回正常赖条,但點擊頭部箭頭返回在MX4上很慢,并不是不執(zhí)行常熙,但是要間隔很久纬乍,實測用了12s。症概。蕾额。目前沒有找到原因。(看看自定義能不能解決)
運行時遇到一個Unknown error: not all success patterns were matched錯誤彼城,重新加載也不行诅蝶,直接運行也不行。 用命令行跑了一下募壕,發(fā)現(xiàn)找不到設備调炬。。舱馅。重新拔插了一下usb就好了缰泡。
傳遞參數(shù)
- 通過在調(diào)用navigate方法時傳入一個對象
this.props.navigation.navigate('RouteName', { /* params go here */ })
- 讀取參數(shù)
this.props.navigation.state.params
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
this.props.navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
}
class DetailsScreen extends React.Component {
render() {
/* 2. Read the params from the navigation state */
const { params } = this.props.navigation.state;
const itemId = params ? params.itemId : null;
const otherParam = params ? params.otherParam : null;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.navigate('Details')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}
自定義header bar
- 每個組件有一個靜態(tài)屬性叫navigationOptions,可以通過這個配置一些參數(shù),例如title (ios默認會居中棘钞,android居左)
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
};
/* render function, etc */
}
class DetailsScreen extends React.Component {
static navigationOptions = {
title: 'Details',
};
/* render function, etc */
}
將this.props放入navigationOptions中使用看起來很方便缠借,但因為這是個靜態(tài)屬性,所以實際上并不會關聯(lián)到任何實例宜猜,自然也不會有props屬性泼返。這里需要將navigationOptions變成一個方法,React Navigation會通過一個包含{navigation, navigationOptions, screenProps}的對象調(diào)用它姨拥。
傳遞參數(shù)設置navigationOptions
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
// 注意params是帶大括號的
const { params } = navigation.state;
return {
title: params ? params.otherParam : 'A Nested Details Screen',
}
};
/* render function, etc */
}
The argument that is passed in to the navigationOptions function is an object with the following properties:
navigation - The navigation prop for the screen, with the screen's route at navigation.state.
screenProps - The props passing from above the navigator component(上層組件傳過來的參數(shù))
navigationOptions - The default or previous options that would be used if new values are not provided
上面只用到了navigation屬性
- 在當前屏幕對navigationOptions進行更新
<Button
title="Update the title"
onPress={() => this.props.navigation.setParams({otherParam: 'Updated!'})}
/>
通過setParams設置了一個新的對象
- 調(diào)整頭部樣式
主要用到三個屬性
headerStyle:設置包裹頭部view的樣式绅喉,可以設置背景顏色
headerTintColor: 渲染返回鍵、標題的顏色叫乌。
headerTitleStyle: 設置文字柴罐、字體、粗細(fontWeight)憨奸?
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
/* render function, etc */
}
這種設置方式只對當前頁面有效革屠。
- 如果要配置對所有導航頁都有效的樣式,應該在StackNavigator的第二個參數(shù)中配置
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
/* The header config from HomeScreen is now here */
navigationOptions: {
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
},
}
);
這樣所有的樣式就一樣了膀藐,如果某個頁面要設置特殊樣式屠阻,可以單獨設置。也可以通過將公共的navigationOptions 通過對象傳入進行修改额各。
- 自定義一個組件作為標題
// 定義一個標題
class LogoTitle extends React.Component {
render() {
return (
<Text style ={ {flex:1, fontSize:30,color:'green',textAlign:'center'}}>
標題
</Text>
);
}
}
class HomeScreen extends React.Component {
static navigationOptions = {
// title: 'Home',
headerTitle:<LogoTitle/>,
};
...以下省略...
相關API可以查看StackNavigator reference