Skip to content

๐Ÿ“ฑ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ ๋„ค๋น„๊ฒŒ์ด์…˜ ํ•™์Šต ์ €์žฅ์†Œ

Notifications You must be signed in to change notification settings

ssi02014/React-Native-Navigation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

11 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ’ป React-Native-Navigation

React-Native-Navigation ์ €์žฅ์†Œ


๐ŸŽฅ App View

๐Ÿ“บ Stack Navigation


๐Ÿ“บ Tab Navigation


๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป React Navigation

๐Ÿ”– 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 ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ๊ณ„์ธต ๊ตฌ์กฐ์™€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์—ญํ• ์„ ํ•˜๋ฉฐ, ๋ชจ๋“  ๋‚ด๋น„๊ฒŒ์ด์…˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ์‹ผ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—ฌ์•ผ ํ•œ๋‹ค.

1


๐Ÿƒ ์„ค์ • ์šฐ์„  ์ˆœ์œ„

  • ๋ฆฌ์•กํŠธ ๋‚ด๋น„๊ฒŒ์ด์…˜์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
    1. Navigation ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์œผ๋กœ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
    2. Screen ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์œผ๋กœ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
    3. ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์ „๋‹ฌ๋˜๋Š” navigation์„ ์ด์šฉํ•ด์„œ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ์œ„์— ๋ฐฉ๋ฒ• ์ค‘ 1๋ฒˆ์€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ ์šฉ๋˜๋Š” ํŠน์ง•์ด ์žˆ๋‹ค. 2, 3๋ฒˆ์€ ํ•ด๋‹น ํ™”๋ฉด์—๋งŒ ์ ์šฉ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉํ•˜๊ณ  ์‹ถ์€ ์†์„ฑ์€ 1๋ฒˆ์„ ์„ ํƒํ•˜๊ณ , ๊ฐœ๋ณ„ ํ™”๋ฉด์—๋งŒ ์ ์šฉ์‹œํ‚ค๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ์—๋Š” 2, 3๋ฒˆ์€ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ž‘์€ ๋ฒ”์œ„์˜ ์„ค์ •์ผ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์ง„๋‹ค. (๊ทธ๋ฆผ ์ฐธ๊ณ )

2


๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜

๐Ÿƒ ํ™”๋ฉด ๊ตฌ์„ฑ

  • ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์€ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋‚ด๋น„๊ฒŒ์ด์…˜์œผ๋กœ, ํ˜„์žฌ ํ™”๋ฉด ์œ„์— ๋‹ค๋ฅธ ํ™”๋ฉด์„ ์Œ“์œผ๋ฉด์„œ ํ™”๋ฉด์„ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค.
  • ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์€ ํ™”๋ฉด ์œ„์— ์ƒˆ๋กœ์šด ํ™”๋ฉด์„ ์Œ“์œผ๋ฉด์„œ(push) ์ด๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ํ™”๋ฉด์„ ๊ณ„์† ์œ ์ง€ํ•ด์•ผํ•œ๋‹ค. ์ด๋Ÿฐ ๊ตฌ์กฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ์œ„์— ์žˆ๋Š” ํ™”๋ฉด์„ ๋“ค์–ด๋‚ด๋ฉด(pop) ์ด์ „ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

3

    //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 ํ•จ์ˆ˜๋Š” ์›ํ•˜๋Š” ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

4

    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 ๋“ฑ์ด ํฌํ•จ๋œ ๊ฐ์ฒด๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค.
    1. style์€ headerTitleStyle์— ์„ค์ •๋œ ๊ฐ’์ด๋‹ค.
    2. 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: ๊ธ€์ž์˜ ์ƒ‰๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ธ€์ž ํฌ๊ธฐ ๋“ฑ ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€์—๋งŒ ์ ์šฉ๋œ๋‹ค.

5

    <Stack.Screen 
        name="List" 
        component={List}
        options={{ 
            headerTitle:'List Screen',
            headerBackTitleVisible: true,
            headerBackTitle: 'Prev',
            headerTitleStyle: { fontSize: 24},
            headerTintColor: '#e74c3c',
        }}
    />

๐Ÿƒ ํƒ€์ดํ‹€ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ

  • iOS, Android์˜ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ์•„์ด์ฝ˜์— ๋™์ผํ•œ ์•„์ด์ฝ˜์ด ๋ Œ๋”๋ง๋˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด headerBackImage์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•ด์„œ ๋‘ ํ”Œ๋žซํผ์ด ๋™์ผํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๋„๋ก ๋ณ€๊ฒฝํ•ด์•ผ ๋œ๋‹ค.
    1. style์€ headerTitleStyle์— ์„ค์ •๋œ ๊ฐ’์ด๋‹ค.
    2. 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์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์œผ๋กœ ํ—ค๋”๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค์ •ํ•˜๋Š” ์†์„ฑ์ž…๋‹ˆ๋‹ค.
    1. float: ํ—ค๋”๊ฐ€ ์ƒ๋‹จ์— ์œ ์ง€๋˜๋ฉฐ ํ•˜๋‚˜์˜ ํ—ค๋”๋ฅผ ์‚ฌ์šฉ
    2. screen: ๊ฐ ํ™”๋ฉด๋งˆ๋‹ค ํ—ค๋”๋ฅผ ๊ฐ€์ง€๋ฉฐ ํ™”๋ฉด ๋ณ€๊ฒฝ๊ณผ ํ•จ๊ป˜ ๋‚˜ํƒ€๋‚˜๊ฑฐ๋‚˜ ์‚ฌ๋ผ์ง
    3. none: ํ—ค๋”๊ฐ€ ๋ Œ๋”๋ง๋˜์ง€ ์•Š์Œ

  • headerShown์€ ํ™”๋ฉด ์˜ต์…˜์œผ๋กœ, Navigator ์ปดํฌ๋„ŒํŠธ์˜ screenOptions์— ์„ค์ •ํ•˜๋ฉด ์ „์ฒด ํ™”๋ฉด์˜ ํ—ค๋”๊ฐ€ ๋ณด์ด์ง€ ์•Š๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ—ค๋”๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด ๋…ธ์น˜ ๋””์ž์ธ ๋ฌธ์ œ๋กœ ํ™”๋ฉด์˜ ์ผ๋ถ€๊ฐ€ ๊ฐ€๋ ค์ง€๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด SafeAreaView๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (iOS)
  • Android ๊ฐ™์€ ๊ฒฝ์šฐ ์ƒํƒœ๋ฐ”์— ๊ฐ€๋ ค์ง€๋Š” ๋ฌธ์ œ๋ฅผ StatusBar๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

6

    //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) ์นด์นด์˜คํ†ก, ์œ ํŠœ๋ธŒ

7

    //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์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์ฒ˜๋Ÿผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋ฒ„ํŠผ์˜ ์•„์ด์ฝ˜์ด ๋“ค์–ด๊ฐˆ ์ž๋ฆฌ์— ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.
    1. color
    2. size
    3. 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์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์„œ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    1. below-icon: ์•„์ด์ฝ˜ ์•„๋ž˜์— ๋ผ๋ฒจ์ด ๋ Œ๋”๋ง๋œ๋‹ค.
    2. beside-icon: ์•„์ด์ฝ˜ ์˜ค๋ฅธ์ชฝ์— ๋ผ๋ฒจ์ด ๋ Œ๋”๋ง๋œ๋‹ค.

8

    <Tab.Navigator 
        initialRouteName="Settings"
        tabBarOptions={{
            labelPosition: 'beside-icon',
        }}
    >
    (...)
    </Tab.Navigator>

  • ๋ผ๋ฒจ์„ ๋ Œ๋”๋งํ•˜์ง€ ์•Š๊ณ  ์•„์ด์ฝ˜๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” tabBarOptions ์†์„ฑ์— showLabel์„ ์ด์šฉํ•˜๋ฉด ํƒญ ๋ฐ”์—์„œ ๋ผ๋ฒจ์ด ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

9

    <Tab.Navigator 
        initialRouteName="Settings"
        tabBarOptions={{
            labelPosition: 'beside-icon',
            showLabel: false,
        }}
    >
    (...)
    </Tab.Navigator>

๐Ÿƒ ์Šคํƒ€์ผ ์ˆ˜์ •ํ•˜๊ธฐ

  • ํƒญ ๋ฐ”์˜ ์Šคํƒ€์ผ์„ ์ˆ˜์ •ํ•˜๋ ค๋ฉด tabBarOptions ์†์„ฑ์— style์˜ ๊ฐ’์œผ๋กœ ์Šคํƒ€์ผ ๊ฐ์ฒด๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

11

    <Tab.Navigator 
        initialRouteName="Settings"
        tabBarOptions={{
            labelPosition: 'beside-icon',
            showLabel: false,
            style: {
                backgroundColor: '#54b7f9',
                borderTopColor: '#fff',
                borderTopWidth: 2,
            }
        }}
    >
    </Tab.Navigator>

  • ํƒญ ๋ฒ„ํŠผ์˜ ์•„์ด์ฝ˜์€ ํ™œ์„ฑํ™” ๋œ ์ƒํƒœ์˜ ์ƒ‰์€ activeTintColor, ๋น„ํ™œ์„ฑํ™”๋œ ์ƒํƒœ์˜ ์ƒ‰์€ inactiveTintColor์„ ์ด์šฉํ•ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

10

    <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๋Š” ๋ฒ„ํŠผ์˜ ์„ ํƒ๋„๋‹ˆ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ด๋‹ค. ์ด ๊ฐ’์„ ์ด์šฉํ•˜๋ฉด ๋ฒ„ํŠผ์˜ ํ™œ์„ฑํ™” ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฒ„ํŠผ์„ ๋ Œ๋”๋งํ•˜๊ฑฐ๋‚˜ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

12

    <Tab.Navigator 
        //(...)
    >
        <Tab.Screen 
            name="Mail" 
            component={Mail}
            options={{
                tabBarLabel: 'index',
                tabBarIcon: props => TabIcon({ 
                    ...props, 
                    name: props.focused ? 'email' : 'email-outline'
                }),
            }}
        />
        (...)
    </Tab.Navigator>

About

๐Ÿ“ฑ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ ๋„ค๋น„๊ฒŒ์ด์…˜ ํ•™์Šต ์ €์žฅ์†Œ

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published