使用react native進行開發,不可避免的會使用到跳轉。鑑於目前react native版本問題。一般使用react-navigation實現跳轉。這也是官方推薦使用的組件。
createStackNavigator 爲您的應用提供一種在屏幕之間轉換的方式,其中每個新屏幕都放置在堆棧頂部。這個是我們實現跳轉所要使用到的API。它的用法
createStackNavigator(RouteConfigs, StackNavigatorConfig);
RouteConfigs參數,我們用來寫路由相關的配置。一般我們寫具有跳轉關係的View配置。比如,有A、B、C三個頁面,我需要A、B、C三個頁面同時具有跳轉關係。即我可以從A跳轉至B,亦可以從A跳轉至C,B跳轉至C等同級跳轉。我們將A、B、C註冊到RouteConfigs參數,同時,我們可以對這些頁面進行一些樣式操作。默認頁面會有標題欄,返回按鈕等樣式。如果不需要,我們可以將其去除等操作。總而言之,我們可以用來註冊我們期望具有跳抓功能的View頁面
StackNavigatorConfig參數,用來設置一些跳轉的默認操作,比如堆棧的默認屏幕視圖,初始路線的參數等設置,按照需求進行設置,不過多做講解。
const HomeStack = createStackNavigator({//設置HomeScreen頁面與SettingView頁面的跳轉註冊
HomeScreen: {
screen: HomeScreen,//註冊View頁面名稱
navigationOptions: () => ({
header: null, //去除標題欄
headerBackTitle: null, //去除返回按鈕
gesturesEnabled: true //是否可以使用手勢來關閉此屏幕。在iOS上默認爲true,在Android上默認爲false
})
},
SettingView: {//註冊設置頁面
screen: SettingView,
navigationOptions: () => ({
header: null, //去除標題欄
headerBackTitle: null, //去除返回按鈕
gesturesEnabled: true //是否可以使用手勢來關閉此屏幕。在iOS上默認爲true,在Android上默認爲false
})
},
MapScreen: {//註冊地圖頁面
screen: MapScreen,
navigationOptions: () => ({
header: null, //去除標題欄
headerBackTitle: null, //去除返回按鈕
gesturesEnabled: true //是否可以使用手勢來關閉此屏幕。在iOS上默認爲true,在Android上默認爲false
})
},
DetailInfo: {//註冊業務詳情頁面
screen: DetailInfo,
navigationOptions: () => ({
header: null, //去除標題欄
headerBackTitle: null, //去除返回按鈕
gesturesEnabled: true //是否可以使用手勢來關閉此屏幕。在iOS上默認爲true,在Android上默認爲false
})
},
Appointment: {//註冊業務列表頁面
screen: Appointment,
navigationOptions: () => ({
header: null, //去除標題欄
headerBackTitle: null, //去除返回按鈕
gesturesEnabled: true //是否可以使用手勢來關閉此屏幕。在iOS上默認爲true,在Android上默認爲false
})
}
},{
initialRouteName:'HomeScreen',
initialRouteParams:{ //設置初始參數
key:'aaaaa',
key1:'bbbbb'
},
});
注意:createStackNavigator與createSwitchNavigator的區別。它兩個作用大致相同。createStackNavigator具有堆棧功能,createSwitchNavigator不具有堆棧功能,createSwitchNavigator的目的是一次只顯示一個屏幕。默認情況下,它不處理後退操作,並在您切換時,將路由重置爲其默認狀態。這是我們從身份驗證流程中想要的確切行爲。
我們進行了跳轉配置後,當然就是如何使用了。
screen
您應用中的每個組件都會navigation
自動提供道具。prop包含各種便利功能,用於在路由的路由器上分派導航操作。
進行跳轉的API https://reactnavigation.org/docs/en/navigation-prop.html
this.props.navigation
navigate - 轉到另一個屏幕,找出它需要採取的行動
goBack - 關閉活動屏幕並向後移動
addListener - 訂閱導航生命週期的更新
isFocused- true如果屏幕聚焦false則返回的功能
state - 當前路線
setParams - 改變路線的參數,傳遞參數
getParam - 獲得具有後備的特定參數,獲取參數
dispatch - 向路由器發送動作
dangerouslyGetParent - 返回父導航器的函數(如果有)
簡單舉例
我們可以使用this.props.navigation.navigate('要跳轉的View名稱')方式進行跳轉,該跳轉方式,會將跳轉的頁面存入棧頂部,當點擊返回按鍵,或者調用this.props.navigation.goBack()方法時返回到上個頁面。
我們如果想要回退到指定的頁面,我們需要得到我們將要回退頁面上一個頁面的頁面key進行回退,調用this.props.navigation.goBack(key)方式回退到指定的頁面。
比如,有A、B、C、D四個頁面。我從A使用this.props.navigation.navigate('B')跳轉到了B頁面,然後使用this.props.navigation.navigate('C')跳轉到了C頁面,然後又跳轉到D頁面,但是我想直接返回到A頁面,如果我按返回鍵,則返回順序是D > C > B > A。不是我想要的結果。我如果之間使用this.props.navigation.navigate('A')的方式跳轉到A,那麼我退出時,會出現A > D > C > B > A。這種情況(當然,有雙擊退出,強制退出操作不在考慮範圍內),設計不太合理。我們可以使用this.props.navigation.goBack(key)這種方式進行返回,我們首先要得到我們要返回的頁面的前一個頁面的頁面KEY,也就是A前面的頁面B頁面的KEY。
let HOME_KEY = this.props.navigation.state.key;//得到當前頁面key
使用以上方式得到頁面key後傳入到D頁面中的this.props.navigation.goBack(key)函數中。我們就能夠返回到原頁面。
使用this.props.navigation.navigate()方法也可以進行傳值。
this.props.navigation.navigate('A', {
session: this.state.session,
ucid: this.state.ucid,
});
取值,包括初始化頁面時的傳遞的初始值,也可以以這種方式取值
const { navigation } = this.props;
let value = navigation.getParam('key', ''); //得到Drawer頁面傳遞的頁面key
let value1 = navigation.getParam('key1', ''); //得到Drawer頁面傳遞的頁面key
底部導航欄 createBottomTabNavigator react-navigation爲我們提供了底部導航欄與頂部導航欄的API,我們只做底部導航欄的講解。
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);
它同樣有兩個參數。RouteConfigs用法與createStackNavigator用法一樣,不做講解。但是,我們會將底部導航所需的View放在次參數中,因爲,底部導航至少會有兩個頁面。
{//RouteConfigs
Home: {
screen: HomeStack,
},
Work: {
screen: WorkStack,
},
}
BottomTabNavigatorConfig,我們用來做一些底部導航欄樣式的一些操作,比如,我們所點擊的圖標,圖標顏色(選中狀態顏色,未選中狀態顏色),圖標下方的字體等等。都在代碼中添加了註釋
//配置底部導航欄(標籤欄),HomeScreen與WorkScreen頁面
const bottomTabNavigator = createBottomTabNavigator({//RouteConfigs
Home: {
screen: HomeStack,
},
Work: {
screen: WorkStack,
},
}, {//BottomTavNavtigtorConfig
defaultNavigationOptions: ({ navigation }) => ({ //用於屏幕的默認導航選項
tabBarIcon: ({ focused, tintColor }) => //設置圖標
getTabBarIcon(navigation, focused, tintColor),
tabBarLabel: navigation.state.routeName === 'Home' ? '首頁' : '工作', //設置圖標下方的字體
}),
tabBarOptions: { //設置圖標的樣式
activeTintColor: '#1E90FF', //活動選項卡的標籤和圖標顏色。選中時顏色
inactiveTintColor: '#979797' //非活動選項卡的標籤和圖標顏色。 未選中時顏色
},
});
//設置底部圖片以及圖片的狀態改變
const getTabBarIcon = (navigation, focused, tintColor) => { //設置圖標默認狀態
const { routeName } = navigation.state;
if (routeName === 'Home') { //設置點擊Home頁面時,圖標狀態
return <Image style={{ //圖標的樣式
width: 25,
height: 25
}}
source={focused ? require('./image/tabbar_home_pressed.png') : require('./image/tabbar_home.png')} /> //返回選中與未選中不同狀態時,圖標的樣式,顏色
} else if (routeName === 'Work') { //設置點擊Work頁面時,圖標狀態
return <Image style={{ ////圖標的樣式
width: 25,
height: 25
}}
source={focused ? require('./image/tabbar_msg_pressed.png') : require('./image/tabbar_msg.png')} /> //返回選中與未選中不同狀態時,圖標的樣式,顏色
}
};
createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig);
同樣的,倆個參數RouteConfigs, DrawerNavigatorConfig。
RouteConfigs
路由CONFIGS對象是從路由名稱映射到一個路由配置,它告訴導航以呈現該路線什麼。我們一般用來寫側拉框所在的頁面。
{//RouteConfigs
Set: {//Set是固定名稱
screen: bottomTabNavigator,
},
}
DrawerNavigatorConfig,用來配置側拉框抽屜的一些默認設置
{
order: ['Set'],//routeNames數組,用於定義抽屜項目的順序。
initialRouteName: 'Set',//初始路由的routeName。
drawerLockMode: 'unlocked',//設置是否響應手勢
//'unlocked' 可以通過手勢和代碼 打開關閉抽屜
//'locked-closed' 抽屜關閉狀態 不能通過手勢打開 只能通過代碼實現
//'locked-open' 抽屜打開狀態 不能通過手勢關閉 只能通過代碼實現
drawerWidth: 300, //抽屜的寬度或返回的功能。
drawerPosition: 'left', //選項是left或right。默認是left位置。
useNativeAnimations: true, //啓用原生動畫。默認是true。
drawerBackgroundColor: '#FAFAFA', //使用抽屜背景獲取某種顏色。默認是white。
//用於呈現抽屜內容的組件,例如導航項。收到navigation抽屜的道具。默認爲DrawerItems
//用於自定義
contentComponent: props => {
return <Drawer {...props} />;
},
//配置抽屜內容 items相關
contentOptions: {
// items: [OtherScreen],//可以修改或覆蓋路由數組 不知道幹嘛用的
// activeItemKey: 'AppInfo', //識別活動路線的關鍵 也不知道幹嘛用的
activeTintColor: 'white', //活動標籤的標籤和圖標顏色
activeBackgroundColor: 'blue', //活動標籤的背景顏色
inactiveTintColor: 'black', //非活動標籤的標籤和圖標顏色
inactiveBackgroundColor: 'red', //非活動標籤的背景顏色
// //按下項目時要調用的函數 不知道是否使用錯誤 一直沒反應
//github上面有答案 在自定義視圖的時候 會有用
// onItemPress(route) {
// console.log('onItemPress'+route);
// },
// itemsContainerStyle: '', //內容部分的樣式對象
// itemStyle: '', //單個項目的樣式對象,可以包含圖標和 / 或標籤
// labelStyle: '', //Text當標籤是字符串時,樣式對象在內容部分內覆蓋樣式
// activeLabelStyle: '', //Text當標籤是字符串(與之合併labelStyle)時,樣式對象覆蓋活動標籤的樣式
// inactiveLabelStyle: '', //Text當標籤是字符串(與之合併labelStyle)時,樣式對象覆蓋非活動標籤的樣式
// iconContainerStyle: '', //樣式對象以覆蓋View圖標容器樣式。
}
}
重點:
//用於自定義
contentComponent: props => {
return <Drawer {...props} />;
},
我們用該方法,可以將抽屜視圖進行自定義。也就是說。我們可以在此頁面編寫抽屜視圖。Drawer就是我的抽屜頁面的視圖。完全可以按照自己想要的效果進行佈局。
this.props.navigation.openDrawer();//打開抽屜
this.props.navigation.closeDrawer();//關閉抽屜
我們可以在抽屜所在的頁面中調用以上方法,進行打開或者關閉抽屜的動作。當然,也可以滑動屏幕來打開或關閉抽屜。
關於react-navigation的使用,我還遠遠未發掘出來,這只是它的一部分,包括它的生命週期,與RN的生命週期的對應,對於它的生命週期的處理。不過,這已經足夠開發出一個優秀的App了。希望以後會更加熟練的使用react-navigation吧。