React-Native-Navigation
Install
依據以下動作即可完成
Install
Basic Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| const { Navigation } = require('react-native-navigation'); const React = require('react'); const { View, Text, StyleSheet } = require('react-native');
const HomeScreen = (props) => { return ( <View style={styles.root}> <Text>Home Screen</Text> </View> ); };
HomeScreen.options = { topBar: { title: { text: 'Home', color: 'white' }, background: { color: '#4d089a' } } }
Navigation.registerComponent('Home', () => HomeScreen);
Navigation.events().registerAppLaunchedListener(async () => { Navigation.setRoot({ root: { stack: { children: [ { component: { name: 'Home' } } ] } } }); });
const styles = StyleSheet.create({ root: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'whitesmoke' } });
|
:::info
Navigation.registerComponent
會建立一個 uniqueId CompoenntId
這個 Id 會是換頁的主要依據
:::
導頁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| const { Navigation } = require('react-native-navigation'); const React = require('react'); const { View, Text, StyleSheet } = require('react-native'); const { Button } = require('react-native');
const HomeScreen = (props) => { return ( <View style={styles.root}> <Text>Home Screen</Text> <Button title='Push Settings Screen' color='#710ce3' onPress={() => Navigation.push(props.componentId, { component: { name: 'Settings', options: { topBar: { title: { text: 'Settings' } } } } })}/> </View> ); };
const SettingScreen = (props) => { return ( <View style={styles.root}> <Text>Setting Screen</Text> </View> ); };
HomeScreen.options = { topBar: { title: { text: 'Home', color: 'white' }, background: { color: '#4d089a' } } }
Navigation.registerComponent('Home', () => HomeScreen); Navigation.registerComponent('Settings', () => SettingScreen);
Navigation.events().registerAppLaunchedListener(async () => { Navigation.setRoot({ root: { stack: { children: [ { component: { name: 'Home' } } ] } } }); });
const styles = StyleSheet.create({ root: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'whitesmoke' } });
|
App Theme
使用的 Style Framwork 是 react-native-elements
裡面也有 Theme
React Native Navigation 也可以設定 Theme
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Navigation.setDefaultOptions({ statusBar: { backgroundColor: '#4d089a' }, topBar: { title: { color: 'white' }, backButton: { color: 'white' }, background: { color: '#4d089a' } } });
|
Tab Stack
一般的App 都會有 Bottom 的 Tap navigation
在 React Native Navigation 中
把剛剛的 Home
Settings
頁面換成兩個 Tab Statck
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| const { Navigation } = require('react-native-navigation'); const React = require('react'); const { View, Text, Button, StyleSheet } = require('react-native');
const HomeScreen = (props) => { return ( <View style={styles.root}> <Text>Hello React Native Navigation 👋</Text>
<Button title='Push Settings Screen' color='#710ce3' onPress={() => Navigation.push(props.componentId, { component: { name: 'Settings' } })} /> </View> ); }; HomeScreen.options = { topBar: { title: { text: 'Home' } }, bottomTab: { text: 'Home' } };
const SettingsScreen = () => { return ( <View style={styles.root}> <Text>Settings Screen</Text> </View> ); } SettingsScreen.options = { topBar: { title: { text: 'Settings' } }, bottomTab: { text: 'Settings' } }
Navigation.registerComponent('Home', () => HomeScreen); Navigation.registerComponent('Settings', () => SettingsScreen);
Navigation.setDefaultOptions({ statusBar: { backgroundColor: '#4d089a' }, topBar: { title: { color: 'white' }, backButton: { color: 'white' }, background: { color: '#4d089a' } }, bottomTab: { fontSize: 14, selectedFontSize: 14 } });
Navigation.events().registerAppLaunchedListener(async () => { Navigation.setRoot({ root: { bottomTabs: { children: [ { stack: { children: [ { component: { name: 'Home' } }, ] } }, { stack: { children: [ { component: { name: 'Settings' } } ] } } ] } } }); });
const styles = StyleSheet.create({ root: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'whitesmoke' } });
|
Bottom Tab 會有 Home
和 Settings
但是在 Home
會有 Button
點擊後還是會 push Settings
進入 Home Stack
這是一般的 App Navigation 的邏輯
Replace Root
Navigation 也提供了覆蓋 Root Stack 的 function
Navigation.setRoot(${rootObject})
執行這個 function 會將 Root 整個覆蓋
範例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| const { Navigation } = require('react-native-navigation'); const React = require('react'); const { View, Text, Button, StyleSheet } = require('react-native');
const LoginScreen = () => { return ( <View style={styles.root}> <Button title='Login' color='#710ce3' onPress={() => Navigation.setRoot(mainRoot)} /> </View> ); };
const HomeScreen = (props) => { return ( <View style={styles.root}> <Text>Hello React Native Navigation 👋</Text>
<Button title='Push Settings Screen' color='#710ce3' onPress={() => Navigation.push(props.componentId, { component: { name: 'Settings' } })} /> </View> ); }; HomeScreen.options = { topBar: { title: { text: 'Home' } }, bottomTab: { text: 'Home' } };
const SettingsScreen = () => { return ( <View style={styles.root}> <Text>Settings Screen</Text> </View> ); } SettingsScreen.options = { topBar: { title: { text: 'Settings' } }, bottomTab: { text: 'Settings' } }
Navigation.registerComponent('Login', () => LoginScreen); Navigation.registerComponent('Home', () => HomeScreen); Navigation.registerComponent('Settings', () => SettingsScreen);
const mainRoot = { root: { bottomTabs: { children: [ { stack: { children: [ { component: { name: 'Home' } }, ] } }, { stack: { children: [ { component: { name: 'Settings' } } ] } } ] } } };
const loginRoot = { root: { component: { name: 'Login' } } };
Navigation.setDefaultOptions({ statusBar: { backgroundColor: '#4d089a' }, topBar: { title: { color: 'white' }, backButton: { color: 'white' }, background: { color: '#4d089a' } }, bottomTab: { fontSize: 14, selectedFontSize: 14 } }); Navigation.events().registerAppLaunchedListener(async () => { Navigation.setRoot(loginRoot); });
const styles = StyleSheet.create({ root: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'whitesmoke' } });
|
基本上定義了一個 loginRoot
和 mainRoot
在登入的時候如果成功則切換到 mainRoot
登出的時候則再度切換回 loginRoot
來簡單的實現了登入登出機制
但是在實際的產品中這樣卻是不足的
因為會先看到 LoginScreen
如果是登入狀態
加上在 React Native 讀取 AsyncStorage 的資料都是非同步的
會看到閃一下 再跳到 MainRoot
在使用者體驗上會很糟糕
所以會需要做一些調整來避免這個狀況
但是這篇篇幅太多
留著後面再說吧