๐ https://reactnavigation.org/
- ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ์์๋ ๋ด๋น๊ฒ์ด์ ๊ธฐ๋ฅ์ ์ง์ํ์ง ์์ผ๋ฏ๋ก ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
- ๋ฆฌ์กํธ ๋ด๋น๊ฒ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ด๋น๊ฒ์ด์ ์ ์ฝ๊ณ ๊ฐ๋จํ๊ฒ ๊ด๋ฆฌํ ์ ์๋๋ก ๋์์ค๋ค.
- ๋ด๋น๊ฒ์ด์ ์ข ๋ฅ๋ก๋ ์คํ(stack), ํญ(tab), ๋๋ก์ด(drawer) ์ธ ์ข ๋ฅ๊ฐ ์๋ค.
//install
yarn add @react-navigation/native
//๋ด๋น๊ฒ์ด์
์์ ํ์ํ ์ข
์์ฑ ์ค์น
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
- ๋ฆฌ์กํธ ๋ด๋น๊ฒ์ด์ ์๋ NavigationContainer ์ปดํฌ๋ํธ, Navigation, Screen ์ปดํฌ๋ํธ๊ฐ ์๋ค.
- Screen ์ปดํฌ๋ํธ๋ ํ๋ฉด์ผ๋ก ์ฌ์ฉ๋๋ ์ปดํฌ๋ํธ์ด๋ค. name๊ณผ component ์์ฑ์ ์ง์ ํด์ผ ํ๋ค. name์ ํ๋ฉด ์ด๋ฆ์ผ๋ก ์ฌ์ฉ๋๋ฉฐ, component์๋ ํ๋ฉด์ผ๋ก ์ฌ์ฉ ๋ ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฌํ๋ค.
- Navigation ์ปดํฌ๋ํธ๋ ํ๋ฉด์ ๊ด๋ฆฌํ๋ ์ค๊ฐ ๊ด๋ฆฌ์ ์ญํ ๋ก ๋ด๋น๊ฒ์ด์ ์ ๊ตฌ์ฑํ๋ฉฐ, ์ฌ๋ฌ ๊ฐ์ Screen ์ปดํฌ๋ํธ๋ฅผ ์์ ์ปดํฌ๋ํธ๋ก ๊ฐ๊ณ ์๋ค.
- NavigationContainer ์ปดํฌ๋ํธ๋ ๋ด๋น๊ฒ์ด์ ์ ๊ณ์ธต ๊ตฌ์กฐ์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ์ปจํ ์ด๋ ์ญํ ์ ํ๋ฉฐ, ๋ชจ๋ ๋ด๋น๊ฒ์ด์ ๊ตฌ์ฑ ์์๋ฅผ ๊ฐ์ผ ์ต์์ ์ปดํฌ๋ํธ์ฌ์ผ ํ๋ค.
- ๋ฆฌ์กํธ ๋ด๋น๊ฒ์ด์
์์ ์ค์ ํ ์ ์๋ ๋ค์ํ ์์ฑ์ ์์ ํ๋ ๋ฐฉ๋ฒ
- Navigation ์ปดํฌ๋ํธ์ ์์ฑ์ผ๋ก ์์ ํ๋ ๋ฐฉ๋ฒ
- Screen ์ปดํฌ๋ํธ์ ์์ฑ์ผ๋ก ์์ ํ๋ ๋ฐฉ๋ฒ
- ํ๋ฉด์ผ๋ก ์ฌ์ฉ๋๋ ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌ๋๋ navigation์ ์ด์ฉํด์ ์์ ํ๋ ๋ฐฉ๋ฒ
- ์์ ๋ฐฉ๋ฒ ์ค 1๋ฒ์ ์์ ์ปดํฌ๋ํธ๋ก ์กด์ฌํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ์ ์ ์ฉ๋๋ ํน์ง์ด ์๋ค. 2, 3๋ฒ์ ํด๋น ํ๋ฉด์๋ง ์ ์ฉ๋๋ค. ๊ทธ๋ ๊ธฐ์ ๊ณตํต์ ์ผ๋ก ์ ์ฉํ๊ณ ์ถ์ ์์ฑ์ 1๋ฒ์ ์ ํํ๊ณ , ๊ฐ๋ณ ํ๋ฉด์๋ง ์ ์ฉ์ํค๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ 2, 3๋ฒ์ ์ฌ์ฉํ๋ค.
- ์์ ๋ฒ์์ ์ค์ ์ผ์๋ก ์ฐ์ ์์๊ฐ ๋์์ง๋ค. (๊ทธ๋ฆผ ์ฐธ๊ณ )
- ์คํ ๋ด๋น๊ฒ์ด์ ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ด๋น๊ฒ์ด์ ์ผ๋ก, ํ์ฌ ํ๋ฉด ์์ ๋ค๋ฅธ ํ๋ฉด์ ์์ผ๋ฉด์ ํ๋ฉด์ ์ด๋ํ๋ ๊ฒ์ด ํน์ง์ด๋ค.
- ์คํ ๋ด๋น๊ฒ์ด์ ์ ํ๋ฉด ์์ ์๋ก์ด ํ๋ฉด์ ์์ผ๋ฉด์(push) ์ด๋ํ๊ธฐ ๋๋ฌธ์ ์ด์ ํ๋ฉด์ ๊ณ์ ์ ์งํด์ผํ๋ค. ์ด๋ฐ ๊ตฌ์กฐ ๋๋ฌธ์ ๊ฐ์ฅ ์์ ์๋ ํ๋ฉด์ ๋ค์ด๋ด๋ฉด(pop) ์ด์ ํ๋ฉด์ผ๋ก ๋์๊ฐ ์ ์๋ค๋ ํน์ง์ด ์๋ค.
//install
yarn add @react-navigation/stack
//import
import {createStackNavigator} from '@react-navigation/stack';
//component import
import Home from '../screens/Home';
import Item from '../screens/Item';
import List from '../screens/List';
// ์คํ ๋ด๋น๊ฒ์ด์
์์ฑ
const Stack = createStackNavigator();
// ํ๋ฉด์ ๊ตฌ์ฑํ๋ Screen, Screen์ ๊ด๋ฆฌํ๋ Navigator ์ปดํฌ๋ํธ
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="List" component={List} />
<Stack.Screen name="Item" component={Item} />
</Stack.Navigator>
);
- ์คํ ๋ด๋น๊ฒ์ด์ ์์ ์ฒซ ๋ฒ์งธ ํ๋ฉด์ผ๋ก ๋์ค๋ ํ๋ฉด์ Navigator ์ปดํฌ๋ํธ์ ์ฒซ ๋ฒ์งธ ์์ Screen ์ปดํฌ๋ํธ์ ๋๋ค. ๋ง์ฝ ์์๋ฅผ ๋ณ๊ฒฝํ๋ค๋ฉด ์ฒซ ํ๋ฉด์ผ๋ก ๋ํ๋๋ ํ๋ฉด์ด ๋ฌ๋ผ์ง๋๋ค.
- ์ปดํฌ๋ํธ ์์๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ ์ธ์๋ initalRouteName ์์ฑ์ ์ด์ฉํด ์ฒซ ๋ฒ์งธ ํ๋ฉด์ ์ง์ ํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
return (
<Stack.Navigator initialRouteName="List">
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="List" component={List} />
<Stack.Screen name="Item" component={Item} />
</Stack.Navigator>
);
- Screen ์ปดํฌ๋ํธ์ component๋ก ์ง์ ๋ ์ปดํฌ๋ํธ๋ ํ๋ฉด์ผ๋ก ์ด์ฉ๋๊ณ navigation์ด props๋ก ์ ๋ฌ๋ฉ๋๋ค.
- navigation์๋ ๋ค์ํ ๊ธฐ๋ฅ์ด ์กด์ฌํ๋๋ฐ ๊ทธ์ค navigate ํจ์๋ ์ํ๋ ํ๋ฉด์ผ๋ก ์ด๋ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํจ์์ ๋๋ค.
const Home = ({ navigation }) => {
return(
<Container>
<StyledText>Home</StyledText>
<Button
title="go to the list screen"
//navigate ํจ์๋ฅผ ์ด์ฉํด์ ์ํ๋ ํ๋ฉด์ ์ด๋ฆ์ ์ ๋ฌํ๋ฉด ํด๋น ํ๋ฉด์ผ๋ก ์ด๋ ๋ฉ๋๋ค.
onPress={() => navigation.navigate('List')}
/>
</Container>
)
};
- ๋ง์ฝ ์ด๋ํ๋ ํ๋ฉด์ด ์ด์ ํ๋ฉด์ ์์ธ ํ๋ฉด์ด๋ผ๋ฉด, ์์ธ ํ๋ฉด์ ์ด๋ค ๋ด์ฉ์ ๋ ๋๋งํด์ผํ๋์ง ์ ๋ฌ ๋ฐ์์ผ ํฉ๋๋ค. navigate ํจ์๋ฅผ ์ด์ฉํ ๋ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํด์ ์ด๋ํ๋ ํ๋ฉด์ ํ์ํ ์ ๋ณด๋ฅผ ํจ๊ป ์ ๋ฌํ๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
- ์ ๋ฌ ๋ ๋ด์ฉ์ ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌ๋๋ route์ params๋ฅผ ํตํด ํ์ธํ ์ ์์ต๋๋ค.
//๋ฐ์ดํฐ ์ ๋ฌ
const _onPress = item => {
navigation.navigate('Item', {id: item._id, name: item.name});
};
//๋ฐ์ดํฐ ํ์ธ
const Item = ({ route }) => {
return (
<Container>
<StyledText>Item</StyledText>
<StyledText>ID: {route.params.id}</StyledText>
<StyledText>Item: {route.params.name}</StyledText>
</Container>
)
};
- ๋ฆฌ์กํธ ๋ด๋น๊ฒ์ด์ ์ cardStyle์ ์ด์ฉํ๋ฉด ์คํ ๋ด๋น๊ฒ์ด์ ์ ํ๋ฉด ๋ฐฐ๊ฒฝ์์ ์์ ํ ์ ์์ต๋๋ค.
- ํ๋ฉด์ ๋ฐฐ๊ฒฝ์์ ์ผ๋ฐ์ ์ผ๋ก ๋์ผํ๊ฒ ์ฌ์ฉํ๋ฏ๋ก, ํ๋ฉด๋ง๋ค ์ค์ ํ๊ธฐ๋ณด๋ค Navigator ์ปดํฌ๋ํธ์ screenOptions์ ์ค์ ํด์ ํ๋ฉด ์ ์ฒด์ ์ ์ฉ๋๋๋ก ํ๋ ๊ฒ์ด ํธํฉ๋๋ค.
<Stack.Navigator
initialRouteName="Home"
screenOptions={{ cardStyle: { backgroundColor: '#ffffff' }}}
>
(...)
</Stack.Navigator>
- ์คํ ๋ด๋น๊ฒ์ด์ ์ ํค๋๋ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ์ ๊ณตํ๊ฑฐ๋ ํ์ดํ์ ํตํด ํ์ฌ ํ๋ฉด์ ์๋ ค์ฃผ๋ ์ญํ ์ ํฉ๋๋ค.
- ํค๋ ํ์ดํ์ Screen ์ปดํฌ๋ํธ์ name ์์ฑ์ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
- Screen ์ปดํฌ๋ํธ์ name ์์ฑ์ ๋ฐ๊พผ๋ค๋ฉด navigate ํจ์์ ์ ๋ฌํ๋ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ ๊ฐ๋ ๋ณ๊ฒฝ๋์ด์ผ ํฉ๋๋ค.
- name ์์ฑ์ ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ฐํธํ์ง๋ง, name ์์ฑ์ ์ด์ฉํ๋ ๊ณณ์ ์ฐพ์๋ค๋๋ฉฐ ๋ชจ๋ ์์ ํด์ผ ํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค. ์ด ๋จ์ ์ ํผํ๋ ๋ฐฉ๋ฒ์ผ๋ก headerTitle ์์ฑ์ ์ด์ฉํ๋ ๊ฒ์ ๋๋ค.
<Stack.Navigator>
(...)
<Stack.Screen
name="List"
component={List}
options={{ headerTitle:'List Screen'}}
/>
</Stack.Navigator>
- headerStyle: ํค๋์ ๋ฐฐ๊ฒฝ์ ๋ฑ์ ์์ ํ๋ ์์ฑ
- headerTitleStyle: ํค๋์ ํ์ดํ ์ปดํฌ๋ํธ์ ์คํ์ผ์ ์์ ํ๋ ์์ฑ
- headerTitleAlign: ํ์ดํ ์ ๋ ฌ ํ๋ ์์ฑ center์ left๋ง ๊ฐ๋ฅ
- headerTitle: headerTitle ์์ฑ์ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์ง์ ํ๋ฉด ํ์ดํ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํ๋ ์ปดํฌ๋ํธ๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
- headerTitle์ ํจ์๊ฐ ์ค์ ๋๋ฉด ํด๋น ํจ์์ ํ๋ผ๋ฏธํฐ๋ก style๊ณผ tintColor ๋ฑ์ด ํฌํจ๋ ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋๋ค.
- style์ headerTitleStyle์ ์ค์ ๋ ๊ฐ์ด๋ค.
- tintColor๋ headerTintColor์ ์ง์ ๋ ๊ฐ์ด ์ ๋ฌ ๋๋ค.
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
cardStyle: { backgroundColor: '#ffffff' },
headerStyle: {
height: 110,
backgroundColor: '#95a5a6',
borderBottomWidth: 5,
borderBottomColor: '#34495e',
},
headerTitleStyle: { color: '#ffffff', fontSize: 24},
headerTitleAlign: 'center',
headerTitle: ({ style }) => (
<MaterialCommunityIcons name="react" style={style} />
)
}}
>
(...)
</Stack.Navigator>
- headerBackTitleVisible: iOS, Android ๋ ํ๋ซํผ์ ๋ฒํผ ํ์ดํ ๋ ๋๋ง ์ฌ๋ถ๋ฅผ ๋์ผํ๊ฒ ์ค์ ํ ์ ์๋ ์์ฑ. true๋ก ํ๋ฉด ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ + ํ์ดํ์ด ๋ณด์ธ๋ค.
- headerBackTitle: ์ด์ ํ๋ฉด์ ์ด๋ฆ์ด ์๋ ๋ค๋ฅธ ๊ฐ์ ์ด์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ headerBackTitle ์์ฑ์ ์ด์ฉํ๋ค.
- headerTintStyle: ๋ฒํผ์ ํ์ดํ๊ณผ ์ด๋ฏธ์ง์ ์์ ๋์ผํ๊ฒ ๋ณ๊ฒฝํ ๋ ์ฌ์ฉํ๋ ์์ฑ
- headerBackTitleStyle: ๊ธ์์ ์๋ฟ๋ง ์๋๋ผ ๊ธ์ ํฌ๊ธฐ ๋ฑ ๋ค์ํ ์คํ์ผ์ ์ง์ ํ ์ ์์ง๋ง ๋ฒํผ์ ํ์ดํ์๋ง ์ ์ฉ๋๋ค.
<Stack.Screen
name="List"
component={List}
options={{
headerTitle:'List Screen',
headerBackTitleVisible: true,
headerBackTitle: 'Prev',
headerTitleStyle: { fontSize: 24},
headerTintColor: '#e74c3c',
}}
/>
- iOS, Android์ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ ์์ด์ฝ์ ๋์ผํ ์์ด์ฝ์ด ๋ ๋๋ง๋๋๋ก ๋ณ๊ฒฝํ๋ ค๋ฉด headerBackImage์ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์ ๋ฌํด์ ๋ ํ๋ซํผ์ด ๋์ผํ ์ด๋ฏธ์ง๋ฅผ ๋ ๋๋งํ๋๋ก ๋ณ๊ฒฝํด์ผ ๋๋ค.
- style์ headerTitleStyle์ ์ค์ ๋ ๊ฐ์ด๋ค.
- tintColor๋ headerTintColor์ ์ง์ ๋ ๊ฐ์ด ์ ๋ฌ ๋๋ค.
<Stack.Screen
name="List"
component={List}
options={{
headerTitle:'List Screen',
headerBackTitleVisible: true,
headerBackTitle: 'Prev',
headerTitleStyle: { fontSize: 24},
headerTintColor: '#e74c3c',
headerBackImage: ({ tintColor }) => {
//๋ ํ๋ซํผ์ ๋ฒํผ ์์น๋ฅผ ๋์ผํ๊ฒ ํ๊ธฐ ์ํด
//ํ๋ซํผ์ ๋ฐ๋ผ ์คํ์ผ์ ๋ค๋ฅด๊ฒ ์ ์ฉ
const style = {
marginRight: 5,
marginLeft: Platform.OS === 'ios' ? 11 : 0,
};
return (
<MaterialCommunityIcons
name='keyboard-backspace'
size={30}
color={tintColor}
style={style}
/>
);
}
}}
/>
- useLayoutEffect Hook์ useEffect์ ๊ฑฐ์ ๋์ผํ๋ฉฐ ๊ฑฐ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋์ํฉ๋๋ค. ์ฃผ์ ์ฐจ์ด์ ์ ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ๋ ์งํ ํ๋ฉด์ด ๋ ๋๋ง ๋๊ธฐ ์ ์ ์คํ๋ฉ๋๋ค. ์ด ํน์ง ๋๋ฌธ์ ํ๋ฉด์ ๋ ๋๋งํ๊ธฐ ์ ์ ๋ณ๊ฒฝํ ๋ถ๋ถ์ด ์๊ฑฐ๋ ์์น ๋ฑ์ ์ธก์ ํด์ผ ํ๋ ์ํฉ์์ ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
- headerLeft์ headerRight์ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์ง์ ํ๋ฉด ํค๋์ ์ผ์ชฝ, ์ค๋ฅธ์ชฝ์ ์ํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
- headerLeft ํ๋ผ๋ฏธํฐ์๋ ๋ค์ํ ๊ฐ๋ค์ด ์ ๋ฌ๋๋๋ฐ, ๊ทธ์ค onPress๋ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ ๊ธฐ๋ฅ์ด ์ ๋ฌ๋ฉ๋๋ค.
- headerRight ํ๋ผ๋ฏธํฐ์๋ tintColor๋ง ์ ๋ฌ๋๋ฏ๋ก, onPress์ ์ํ๋ ํ๋์ ์ ์ํด์ค์ผ ํฉ๋๋ค. navigation์์ ์ ๊ณตํ๋ ๋ค์ํ ํจ์ ์ค popToTop ํจ์๋ ํ์ฌ ์์ฌ ์๋ ๋ชจ๋ ํ๋ฉด์ ๋ด๋ณด๋ด๊ณ ์ฒซ ํ๋ฉด์ผ๋ก ๋์๊ฐ๋ ๊ธฐ๋ฅ์ ๋๋ค.
import React, { useLayoutEffect } from 'react';
const Item = ({ navigation, route }) => {
useLayoutEffect(() => {
navigation.setOptions({
headerBackTitleVisible: false,
headerTintColor: '#ffffff',
headerLeft: ({ onPress, tintColor }) => {
return (
<MaterialCommunityIcons
name="keyboard-backspace"
size={30}
style={{ marginLeft: 11 }}
color={tintColor}
onPress={onPress}
/>
)
},
headerRight: ({ tintColor }) => {
return (
<MaterialCommunityIcons
name="home-variant"
size={30}
style={{ marginRight: 11 }}
color={tintColor}
onPress={() => navigation.popToTop()}
/>
)
},
});
}, []);
- headerMods๋ Navigation์ปดํฌ๋ํธ์ ์์ฑ์ผ๋ก ํค๋๋ฅผ ๋ ๋๋งํ๋ ๋ฐฉ๋ฒ์ ์ค์ ํ๋ ์์ฑ์
๋๋ค.
- float: ํค๋๊ฐ ์๋จ์ ์ ์ง๋๋ฉฐ ํ๋์ ํค๋๋ฅผ ์ฌ์ฉ
- screen: ๊ฐ ํ๋ฉด๋ง๋ค ํค๋๋ฅผ ๊ฐ์ง๋ฉฐ ํ๋ฉด ๋ณ๊ฒฝ๊ณผ ํจ๊ป ๋ํ๋๊ฑฐ๋ ์ฌ๋ผ์ง
- none: ํค๋๊ฐ ๋ ๋๋ง๋์ง ์์
- headerShown์ ํ๋ฉด ์ต์ ์ผ๋ก, Navigator ์ปดํฌ๋ํธ์ screenOptions์ ์ค์ ํ๋ฉด ์ ์ฒด ํ๋ฉด์ ํค๋๊ฐ ๋ณด์ด์ง ์๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
- ํค๋๊ฐ ์ฌ๋ผ์ง๋ฉด ๋ ธ์น ๋์์ธ ๋ฌธ์ ๋ก ํ๋ฉด์ ์ผ๋ถ๊ฐ ๊ฐ๋ ค์ง๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด SafeAreaView๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. (iOS)
- Android ๊ฐ์ ๊ฒฝ์ฐ ์ํ๋ฐ์ ๊ฐ๋ ค์ง๋ ๋ฌธ์ ๋ฅผ StatusBar๋ฅผ ํตํด ํด๊ฒฐ ๊ฐ๋ฅ
//headerShown
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
//SageAreaView
const Container = styled.SafeAreaView`
flex: 1;
justify-content: center;
align-items: center;
`;
//StatusBar
<StatusBar
barStyle="dark-content"
backgroundColor="#ffffff"
/>
- ํญ ๋ด๋น๊ฒ์ด์ ์ ๋ณดํต ํ๋ฉด ์๋ ์๋์ ์์นํ๋ฉฐ, ํญ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ฒํผ๊ณผ ์ฐ๊ฒฐ๋ ํ๋ฉด์ผ๋ก ์ด๋ํ๋ ๋ฐฉ์์ผ๋ก ๋์ํฉ๋๋ค. ex) ์นด์นด์คํก, ์ ํ๋ธ
//install
yarn add @react-navigation/bottom-tabs
- createBottomTabNavigatorํจ์๋ฅผ ์ด์ฉํด ํญ ๋ด๋น๊ฒ์ด์ ์ ์์ฑ
- ํญ ๋ด๋น๊ฒ์ด์ ์๋ ์คํ ๋ด๋น๊ฒ์ด์ ๊ณผ ๋์ผํ๊ฒ Navigator ์ปดํฌ๋ํธ, Screen ์ปดํฌ๋ํธ๊ฐ ์๋ค. ์ญํ ์ ๋์ผํ๋ค.
- initalRouteName ์์ฑ์ ์ด์ฉํด ํญ ๋ฒํผ์ ์์๋ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ๋๋ง ๋๋ ์ฒซ ๋ฒ์งธ ํ๋ฉด์ ๋ณ๊ฒฝํ ์ ์๋ค.
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
const TabNavigation = () => {
return (
<Tab.Navigator initialRouteName="Settings">
<Tab.Screen name="Mail" component={Mail} />
<Tab.Screen name="Meet" component={Meet} />
<Tab.Screen name="Settings" component={Settings} />
</Tab.Navigator>
)
};
- ํญ ๋ฒํผ์ ์์ด์ฝ์ ๋ ๋๋งํ๋ ๋ฐฉ๋ฒ์ tabBarIcon์ ์ด์ฉํ๋ ๊ฒ์ด๋ค. ์คํ ๋ด๋น๊ฒ์ด์
์ฒ๋ผ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์ง์ ํ๋ฉด ๋ฒํผ์ ์์ด์ฝ์ด ๋ค์ด๊ฐ ์๋ฆฌ์ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ค.
- color
- size
- focused
import { MaterialCommunityIcons } from '@expo/vector-icons';
const TabIcon = ({ name, size, color}) => {
return (
<MaterialCommunityIcons
name={name}
size={size}
color={color}
/>
);
}
<Tab.Navigator initialRouteName="Settings">
<Tab.Screen
name="Mail"
component={Mail}
options={{
tabBarIcon: props => TabIcon({ ...props, name: 'email'})
}}
/>
(...)
</Tab.Navigator>
- ๋ง์ฝ Screen ์ปดํฌ๋ํธ๋ง๋คํญ ๋ฒํผ ์์ด์ฝ์ ์ง์ ํ์ง ์๊ณ ํ๊ณณ์์ ๋ชจ๋ ๋ฒํผ์ ์์ด์ฝ์ ๊ด๋ฆฌํ๊ณ ์ถ์ ๊ฒฝ์ฐ Navigator ์ปดํฌ๋ํธ์ screenOptions ์์ฑ์ ์ฌ์ฉํด์ ๊ด๋ฆฌํ ์ ์๋ค.
<Tab.Navigator
initialRouteName="Settings"
screenOptions={({ route }) ({
tabBarIcon: props => {
let name = '';
if (route.name === 'Mail') name = 'email';
else if (route.name === 'Meer') name = 'video';
else name = 'account-settings';
return TabIcon({ ...props, name });
}
})}
>
<Tab.Screen name="Mail" component={Mail}/>
</Tab.Navigator>
- ๋ฒํผ ์์ด์ฝ ์๋์ ๋ ๋๋ง๋๋ ๋ผ๋ฒจ(Label)์ Screen ์ปดํฌ๋ํธ์ name ๊ฐ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ํญ ๋ฒํผ์ ๋ผ๋ฒจ์ tabBarLabel์ ์ด์ฉํด์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
<Tab.Navigator initialRouteName="Settings">
<Tab.Screen
name="Mail"
component={Mail}
options={{
tabBarLabel: 'index',
tabBarIcon: props => TabIcon({ ...props, name: 'email'})
}}
/>
(...)
</Tab.Navigator>
- ๋ผ๋ฒจ์ ๋ฒํผ ์์ด์ฝ์ ์๋๊ฐ ์๋ ์์ด์ฝ ์์ ๋ ๋๋ง๋๋๋ก ๋ณ๊ฒฝํ๊ณ ์ถ์ผ๋ฉด tabBarOptions ์์ฑ์ labelPosition์ ๊ฐ์ ๋ณ๊ฒฝํด์ ์กฐ์ ํ ์ ์์ต๋๋ค.
- below-icon: ์์ด์ฝ ์๋์ ๋ผ๋ฒจ์ด ๋ ๋๋ง๋๋ค.
- beside-icon: ์์ด์ฝ ์ค๋ฅธ์ชฝ์ ๋ผ๋ฒจ์ด ๋ ๋๋ง๋๋ค.
<Tab.Navigator
initialRouteName="Settings"
tabBarOptions={{
labelPosition: 'beside-icon',
}}
>
(...)
</Tab.Navigator>
- ๋ผ๋ฒจ์ ๋ ๋๋งํ์ง ์๊ณ ์์ด์ฝ๋ง ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ tabBarOptions ์์ฑ์ showLabel์ ์ด์ฉํ๋ฉด ํญ ๋ฐ์์ ๋ผ๋ฒจ์ด ๋ ๋๋ง๋์ง ์๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
<Tab.Navigator
initialRouteName="Settings"
tabBarOptions={{
labelPosition: 'beside-icon',
showLabel: false,
}}
>
(...)
</Tab.Navigator>
- ํญ ๋ฐ์ ์คํ์ผ์ ์์ ํ๋ ค๋ฉด tabBarOptions ์์ฑ์ style์ ๊ฐ์ผ๋ก ์คํ์ผ ๊ฐ์ฒด๋ฅผ ์ค์ ํ์ฌ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
<Tab.Navigator
initialRouteName="Settings"
tabBarOptions={{
labelPosition: 'beside-icon',
showLabel: false,
style: {
backgroundColor: '#54b7f9',
borderTopColor: '#fff',
borderTopWidth: 2,
}
}}
>
</Tab.Navigator>
- ํญ ๋ฒํผ์ ์์ด์ฝ์ ํ์ฑํ ๋ ์ํ์ ์์ activeTintColor, ๋นํ์ฑํ๋ ์ํ์ ์์ inactiveTintColor์ ์ด์ฉํด ์ค์ ํ ์ ์์ต๋๋ค.
<Tab.Navigator
initialRouteName="Settings"
tabBarOptions={{
labelPosition: 'beside-icon',
showLabel: false,
style: {
backgroundColor: '#54b7f9',
borderTopColor: '#fff',
borderTopWidth: 2,
},
activeTintColor: '#fff',
inactiveTintColor: '#0B92E9',
}}
>
</Tab.Navigator>
- ๋ฒํผ์ ์์ด์ฝ์ ์ค์ ํ๊ธฐ ์ํด barTabIcon์ ์ค์ ํ ํจ์์๋ ํ๋ผ๋ฏธํฐ๋ก size, color, focused๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋๋๋ฐ. ์ด ๊ฐ ์ค focused๋ ๋ฒํผ์ ์ ํ๋๋ ์ํ๋ฅผ ๋ํ๋ด๋ ๊ฐ์ด๋ค. ์ด ๊ฐ์ ์ด์ฉํ๋ฉด ๋ฒํผ์ ํ์ฑํ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฒํผ์ ๋ ๋๋งํ๊ฑฐ๋ ์คํ์ผ์ ๋ณ๊ฒฝํ ์ ์๋ค.
<Tab.Navigator
//(...)
>
<Tab.Screen
name="Mail"
component={Mail}
options={{
tabBarLabel: 'index',
tabBarIcon: props => TabIcon({
...props,
name: props.focused ? 'email' : 'email-outline'
}),
}}
/>
(...)
</Tab.Navigator>