๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • GDG on campus Ewha Tech Blog
3-1๊ธฐ ์Šคํ„ฐ๋””/React Native

[5์ฃผ์ฐจ] ๋‚ด๋น„๊ฒŒ์ด์…˜

by somsoming 2021. 11. 22.

๐Ÿ”Ž 8์žฅ ๋‚ด๋น„๊ฒŒ์ด์…˜


 

๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ธ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ๋งŒ๋“ค์–ด๋ณด์ž.

๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์•ผํ•œ๋‹ค.

npm install --save @react-navigation/native

๋ฆฌ์•กํŠธ ๋‚ด๋น„๊ฒŒ์ด์…˜์€ ๊ฐ ๊ธฐ๋Šฅ๋ณ„๋กœ ๋ชจ๋“ˆ์ด ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด ์ดํ›„์—๋„ ์‚ฌ์šฉํ•˜๋Š” ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ถ”๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์•ผํ•œ๋‹ค.

 

1. ๋ฆฌ์•กํŠธ ๋„ค๋น„๊ฒŒ์ด์…˜

  • ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜
  • ํƒญ ๋‚ด๋น„๊ฒŒ์ด์…˜
  • ๋“œ๋กœ์–ด ๋‚ด๋น„๊ฒŒ์ด์…˜

 

๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ๊ตฌ์กฐ
  • Screen ์ปดํฌ๋„ŒํŠธ : ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ
    • name, component ์†์„ฑ์„ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค.
    • ํ•ญ์ƒ navigation๊ณผ route๊ฐ€ props๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • Navigation ์ปดํฌ๋„ŒํŠธ : ํ™”๋ฉด์„ ๊ด€๋ฆฌํ•˜๋Š” ์ค‘๊ฐ„ ๊ด€๋ฆฌ์ž ์—ญํ• 
    • ์—ฌ๋Ÿฌ ๊ฐœ์˜ Screen ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ–๊ณ  ์žˆ๋‹ค.
  • NavigationContainer ์ปดํฌ๋„ŒํŠธ : ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ๊ณ„์ธต ๊ตฌ์กฐ์™€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์—ญํ• 
    • ๋ชจ๋“  ๋‚ด๋น„๊ฒŒ์ด์…˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ฐ์‹ผ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ

 

 

์„ค์ • ์šฐ์„  ์ˆœ์œ„

๋ฆฌ์•กํŠธ ๋‚ด๋น„์—๊ธฐ์…˜์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

  • Navigator ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์œผ๋กœ ์ˆ˜์ •
    • ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ ์šฉ๋œ๋‹ค.
    • ๋ชจ๋“  ํ™”๋ฉด์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉํ•˜๊ณ  ์‹ถ์€ ์†์„ฑ์ธ ๊ฒฝ์šฐ ์ด์šฉ
  • Screen ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์œผ๋กœ ์ˆ˜์ •
  • ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์ „๋‹ฌ๋˜๋Š” navigation์„ ์ด์šฉํ•ด์„œ ์ˆ˜์ •
    • ๊ฐœ๋ณ„ํ™”๋ฉด์—๋งŒ ์ ์šฉ๋˜๋Š” ์†์„ฑ์ธ ๊ฒฝ์šฐ Screen ์ปดํฌ๋„ŒํŠธ ํ˜น์€ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ์ˆ˜์ •

 

์ž‘์€ ๋ฒ”์œ„์˜ ์„ค์ •์ผ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์œผ๋ฏ€๋กœ, Screen ์ปดํฌ๋„ŒํŠธ์™€ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ๋™์ผํ•œ ์˜ต์…˜์ด ์ ์šฉ๋˜์—ˆ๋‹ค๋ฉด ํ™”๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ์„ค์ •์ด ์šฐ์„ ํ•œ๋‹ค.

 

 

 

 

2. ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜

npm install @react-navigation/stack
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๋‚ด๋น„๊ฒŒ์ด์…˜
  • ํ˜„์žฌ ํ™”๋ฉด ์œ„์— ๋‹ค๋ฅธ ํ™”๋ฉด์„ ์Œ“์œผ๋ฉด์„œ(push) ํ™”๋ฉด ์ด๋™
  • ์ด์ „ ํ™”๋ฉด์„ ๊ณ„์† ์œ ์ง€ํ•˜๋ฏ€๋กœ, ๊ฐ€์žฅ ์œ„์˜ ํ™”๋ฉด์„ ๋“ค์–ด๋‚ด๋ฉด(pop) ์ด์ „ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ„๋‹ค.
  • ์—ฌ๋Ÿฌ ๋ชฉ๋ก ์ค‘ ํŠน์ • ํ•ญ๋ชฉ์˜ ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ

 

 

ํ™”๋ฉด ๊ตฌ์„ฑ

 

src/Screens

  • ์ฒซ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉํ•  Home ํ™”๋ฉด ์ž‘์„ฑ
const Home = () => {
    return(
        <Container>
            <StyledText>Home</StyledText>
            <Button title="go to the list screen" />
        </Container>
    );
};

export default Home;
  • List ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋  ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ : ํ™”๋ฉด์—์„œ ์‚ฌ์šฉํ•  ์ž„์‹œ ๋ชฉ๋ก ์ƒ์„ฑ ํ›„, ํ•ญ๋ชฉ ์ˆ˜๋งŒํผ ๋ฒ„ํŠผ์„ ์ƒ์„ฑ
  • ๋ชฉ๋ก์˜ ์ƒ์„ธ์ •๋ณด๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ ์ž‘์„ฑ

 

src/navigations

const Stack = createStackNavigator();

const StackNavigation = () => {
    return(
        <Stack.Navigator>
            <Stack.Screen name="Home" component={Home} />
            <Stack.Screen name="List" component={List} />
            <Stack.Screen name="Item" component={Item} />
        </Stack.Navigator>
    );
};
  • createStackNavigator ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ์ƒ์„ฑ
  • ์ƒ์„ฑ๋œ ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์—๋Š” ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๋Š” Screen ์ปดํฌ๋„ŒํŠธ์™€ Screen ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” Navigator ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค.
  • Navigator ์ปดํฌ๋„ŒํŠธ ์•ˆ์— Screen ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์ž‘์„ฑํ•˜๊ณ , ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ Screen ์ปดํฌ๋„ŒํŠธ์˜ component๋กœ ์ง€์ •ํ•œ๋‹ค.

 

src/App.js

const App = () => {
    return (
        <NavigationContainer>
            <StackNavigation/>
        </NavigationContainer>
    );
};

NavigationContainer ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•ด ์ž‘์„ฑ๋œ ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ๊ฐ์‹ธ๋„๋ก ํ•œ๋‹ค.

→ ์ฒซ ๋ฒˆ์งธ๋กœ ๋‚˜์˜ค๋Š” ํ™”๋ฉด์€ Navigator ์ปดํฌ๋„ŒํŠธ์˜ ์ฒซ๋ฒˆ์งธ ์ž์‹ Screen ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์˜ ์ˆœ์„œ ๋ณ€๊ฒฝ ๋˜๋Š” initialRouteName ์†์„ฑ์„ ์ด์šฉํ•ด ์ฒซ ๋ฒˆ์งธ ํ™”๋ฉด์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

ํ™”๋ฉด ์ด๋™

  • Screen ์ปดํฌ๋„ŒํŠธ์˜ component๋กœ ์ง€์ •๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ํ™”๋ฉด์œผ๋กœ ์ด์šฉ๋˜๊ณ  navigation์ด props๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • navigate ํ•จ์ˆ˜ : ์›ํ•˜๋Š” ํ™”๋ฉด์œผ๋กœ ์ด๋™

 

Home ํ™”๋ฉด์—์„œ props๋กœ ์ „๋‹ฌ๋˜๋Š” navigation์„ ์‚ฌ์šฉํ•ด์„œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด List ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ํ•ด๋ณด์ž.

const Home = ({ navigation }) => {
    return(
        <Container>
            <StyledText>Home</StyledText>
            <Button 
                title="go to the list screen"
                onPress={() => navigation.navigate('List')}
            />
        </Container>
    );
};
  • navigation์— ์žˆ๋Š” navigate ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ์›ํ•˜๋Š” ํ™”๋ฉด์˜ ์ด๋ฆ„์„ ์ „๋‹ฌํ•˜๋ฉด ํ•ด๋‹น ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.
    • ์ „๋‹ฌ๋˜๋Š” ํ™”๋ฉด ์ด๋ฆ„์€ Screen ์ปดํฌ๋„ŒํŠธ์˜ name ๊ฐ’ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ž…๋ ฅ

 

 

navigate ํ•จ์ˆ˜ ์ด์šฉ ์‹œ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ด์„œ ์ด๋™ํ•˜๋Š” ํ™”๋ฉด์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.

const List = ({ navigation }) => {
    const _onPress = item => {
        navigation.navigate('Item', { id: item._id, name: item.name });
    };

Item ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋ฉด์„œ ํ•ญ๋ชฉ์˜ id์™€ name์„ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๋„๋ก ํ•œ๋‹ค.

์ „๋‹ฌ๋œ ๋‚ด์šฉ์€ ์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์ „๋‹ฌ๋˜๋Š” route์˜ params๋ฅผ ํ†ตํ•ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

const Item = ({ route }) => {
    return(
        <Container>
            <StyledText>Item</StyledText>
            <StyledText>Id: {route.params.id}</StyledText>
            <StyledText>Name: {route.params.name}</StyledText>
        </Container>
    );
};

์ „๋‹ฌ๋ฐ›์€ params๋ฅผ ์ด์šฉํ•˜์—ฌ ํ™”๋ฉด์— id์™€ name์„ ์ถœ๋ ฅํ•œ๋‹ค.

 

 

ํ™”๋ฉด ๋ฐฐ๊ฒฝ์ƒ‰ ์ˆ˜์ •ํ•˜๊ธฐ

src/screens/Home.js

const Container = styled.View`
    background-color: #ffffff;
    align-items: center;
`;
  • ํ™”๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ „์ฒด ์˜์—ญ์„ ์ฐจ์ง€ํ•˜๋„๋ก ์Šคํƒ€์ผ์— flex: 1 ์„ ์„ค์ •ํ•œ๋‹ค.
  • ์ƒํ™ฉ์— ๋”ฐ๋ผ ํ™”๋ฉด ์ „์ฒด๋ฅผ ์ฐจ์ง€ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ ๋ฆฌ์•กํŠธ ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ์„ค์ •์„ ์ˆ˜์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ•œ๋‹ค.
  • const StackNavigation = () => {
        return(
            <Stack.Navigator 
                initialRouteName="Home"
                screenOptions={{ cardStyle: {backgroundColor: '#ffffff'} }}    
            >
  • cardStyle์„ ์ด์šฉํ•ด ์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ํ™”๋ฉด ๋ฐฐ๊ฒฝ์ƒ‰ ์ˆ˜์ •.
  • ํ™”๋ฉด ๋ฐฐ๊ฒฝ์ƒ‰์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ™”๋ฉด๋งˆ๋‹ค ์„ค์ •ํ•˜๊ธฐ๋ณด๋‹ค Navigation ์ปดํฌ๋„ŒํŠธ์—์„œ ์„ค์ •ํ•ด ํ™”๋ฉด ์ „์ฒด์— ์ ์šฉ๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•˜๋‹ค.
  • ํŠน์ •ํ™”๋ฉด๋งŒ ๋ฐฐ๊ฒฝ์ƒ‰์„ ๋‹ค๋ฅด๊ฒŒ ์ง€์ •ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ Screen ์ปดํฌ๋„ŒํŠธ์—์„œ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง์ ‘ ๋ฐฐ๊ฒฝ์ƒ‰์„ ์ง€์ •ํ•œ๋‹ค.

 

 

ํ—ค๋” ์ˆ˜์ •ํ•˜๊ธฐ

์Šคํƒ ๋‚ด๋น„๊ฒŒ์ด์…˜์˜ ํ—ค๋”๋Š” ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ํƒ€์ดํ‹€์„ ํ†ตํ•ด ํ˜„์žฌ ํ™”๋ฉด์„ ์•Œ๋ ค์ค€๋‹ค.

 

 

ํƒ€์ดํ‹€ ์ˆ˜์ •

  • Screen ์ปดํฌ๋„ŒํŠธ์˜ name ์†์„ฑ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ → name์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ํƒ€์ดํ‹€ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฒ•.
  • name ๊ฐ’ ๋ณ€๊ฒฝ ์‹œ navigate ํ•จ์ˆ˜์— ์ „๋‹ฌํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’๋„ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•œ๋‹ค.
  • const List = ({ navigation }) => {
        const _onPress = item => {
            navigation.navigate('Detail', { id: item._id, name: item.name });
        };
  • name ์†์„ฑ์„ ์ด์šฉํ•˜๋Š” ๊ณณ์„ ๋ชจ๋‘ ์ฐพ์•„ ์ˆ˜์ •ํ•ด์•ผํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

 

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” headerTitle ์†์„ฑ์„ ์ด์šฉํ•˜๋Š” ๋ฒ•์ด ์žˆ๋‹ค.

const StackNavigation = () => {
    return(
        <Stack.Navigator 
            initialRouteName="Home"
            screenOptions={{ cardStyle: {backgroundColor: '#ffffff'} }}    
        >
            <Stack.Screen name="Home" component={Home} />
            <Stack.Screen 
                name="List" 
                component={List} 
                options={{ headerTitle: 'List Screen' }}
            />
            <Stack.Screen name="Detail" component={Item} />
        </Stack.Navigator>
    );
};

๊ฐœ๋ณ„ ํ™”๋ฉด์„ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ Screen ์ปดํฌ๋„ŒํŠธ์˜ options๋ฅผ ์ด์šฉํ•œ๋‹ค.

๋ชจ๋“  ํ™”๋ฉด์—์„œ ๊ฐ™์€ ํƒ€์ดํ‹€์ด ๋‚˜ํƒ€๋‚˜๋„๋ก ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฉด Navigator ์ปดํฌ๋„ŒํŠธ์˜ screenOptions ์†์„ฑ์— headerTitle์„ ์ง€์ •ํ•œ๋‹ค.

 

 

์Šคํƒ€์ผ ์ˆ˜์ •

  • headerStyle : ํ—ค๋”์˜ ๋ฐฐ๊ฒฝ์ƒ‰ ๋“ฑ์„ ์ˆ˜์ •
  • headerTitleStyle : ํ—ค๋”์˜ ํƒ€์ดํ‹€ ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ ์ˆ˜์ •
const StackNavigation = () => {
    return(
        <Stack.Navigator 
            initialRouteName="Home"
            screenOptions={{ 
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#95a5a6',
                    borderBottomWidth: 5,
                    borderBottomColor: '#34495e',
                },
                headerTitleStyle: { color: '#ffffff', fontSize: 24 },
                headerTitleAlign: 'center',

            }}    
        >
    </Stack.Navigator>
);
};

๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ ํƒ€์ดํ‹€์„ ๋™์ผํ•˜๊ฒŒ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” headerTitleAlign ์†์„ฑ์„ ์ง€์ •ํ•œ๋‹ค.

 

 

 

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

 

ํƒ€์ดํ‹€์— ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ Œ๋”๋งํ•˜๊ธฐ ์œ„ํ•ด์„œ headerTitle ์†์„ฑ์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค.

  • style๊ณผ tintColor๋ฅผ ํฌํ•จํ•œ ๊ฐ์ฒด๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ.
  • style : headerTitleStyle์— ์„ค์ •๋œ ๊ฐ’
  • tintColor : headerTintColor์— ์ง€์ •๋œ ๊ฐ’

 

const StackNavigation = () => {
    return(
        <Stack.Navigator 
            initialRouteName="Home"
            screenOptions={{ 
               ...
                headerTitleStyle: { color: '#ffffff', fontSize: 24 },
                headerTitleAlign: 'center',
                headerTitle: ({ style }) => (
                    <MaterialCommunityIcons name="react" style={style} />
                ),
            }}
  • ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋˜๋Š” style์„ ์ด์šฉํ•˜์—ฌ headerTitleStyle์— ์ง€์ •ํ•œ ์Šคํƒ€์ผ๊ณผ ๋™์ผํ•œ ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜๋„๋กํ•œ๋‹ค.
  • ๋ฐ˜ํ™˜๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” vector-icons์—์„œ ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•ด ๋ฆฌ์•กํŠธ ๋กœ๊ณ ๊ฐ€ ๋ Œ๋”๋ง๋˜๋„๋ก ํ•œ๋‹ค.

 

 

๋ฒ„ํŠผ ์ˆ˜์ •ํ•˜๊ธฐ

์ด์ „ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ํ—ค๋” ์™ผ์ชฝ์— ์žˆ๋Š” ๋ฒ„ํŠผ์„ ์ˆ˜์ •ํ•ด๋ณด์ž.

<Stack.Screen 
    name="List" 
    component={List} 
    options={{ 
    headerTitle: 'List Screen',
    headerBackTitleVisible: true,
    headerBackTitle: 'Prev',
    }}
/>
  • iOS์™€ ์•ˆ๋“œ๋กœ์ด๋“œ ํ”Œ๋žซํผ ๋ฒ„ํŠผ ํƒ€์ดํ‹€ ๋ Œ๋”๋ง ์—ฌ๋ถ€๋ฅผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด headerBackTitleVisible์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€์— ์ด์ „ ํ™”๋ฉด์˜ ์ด๋ฆ„์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐ’์„ ์ด์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ headerBackTitle ์„ ์ด์šฉํ•œ๋‹ค.

 

 

๋ฒ„ํŠผ ์Šคํƒ€์ผ ์ˆ˜์ •ํ•˜๊ธฐ

 

headerBackTitleStyle์„ ์ด์šฉํ•ด ๋ฒ„ํŠผ ํƒ€์ดํ‹€์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€๊ณผ ์ด๋ฏธ์ง€ ์ƒ‰์„ ๋™์ผํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด headerTintColor๋ฅผ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.

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

 

 

 

๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ

 

๋‘ ํ”Œ๋žซํผ์˜ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ์•„์ด์ฝ˜์— ๋™์ผํ•œ ์•„์ด์ฝ˜์ด ๋ Œ๋”๋ง๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด headerBackImage์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•ด ๋‘ ํ”Œ๋žซํผ์ด ๋™์ผํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ด๋ณด์ž.

 

<Stack.Screen 
        name="List" 
        component={List} 
        options={{ 
       ...
        headerBackImage: ({ tintColor }) => {
        const style = {
        marginRight: 5,
        marginLeft: Platform.OS === 'ios'? 11 : 0,
        };
        return(
        <MaterialCommunityIcons
        name="keyboard-backspace"
        size={30}
        color={tintColor}
        style={style}
			/>
		);
       },
    }}
/>

headerBackImage์˜ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ „๋‹ฌ๋˜๋Š” tintColor ๊ฐ’์„ ์ด์šฉํ•ด ์•„์ด์ฝ˜์˜ ์ƒ‰์„ ์ง€์ •ํ•˜๊ณ , ๋‘ ํ”Œ๋žซํผ์˜ ๋ฒ„ํŠผ ์œ„์น˜๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ”Œ๋žซํผ์— ๋”ฐ๋ผ ์Šคํƒ€์ผ์„ ๋‹ค๋ฅด๊ฒŒ ์ ์šฉํ•œ๋‹ค.

 

 

  • useLayoutEffect Hook ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ ์งํ›„ ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋˜๊ธฐ ์ „์— ์‹คํ–‰๋œ๋‹ค.
  • headerLeft, headerRight์— ๊ฐ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  • navigation์—์„œ ์ œ๊ณตํ•˜๋Š” popToTop ํ•จ์ˆ˜๋Š” ํ˜„์žฌ ์Œ“์—ฌ์žˆ๋Š” ๋ชจ๋“  ํ™”๋ฉด์„ ๋‚ด๋ณด๋‚ด๊ณ  ์ฒซ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

 

 

ํ—ค๋” ๊ฐ์ถ”๊ธฐ

 

headerMode๋‚˜ headerShown์„ ์‚ฌ์šฉํ•˜์—ฌ ํ—ค๋”๋ฅผ ๊ฐ์ถฐ๋ณด์ž.

headerMode

  • float : ํ—ค๋”๊ฐ€ ์ƒ๋‹จ์— ์œ ์ง€๋˜๋ฉฐ ํ•˜๋‚˜์˜ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • screen : ๊ฐ ํ™”๋ฉด๋งˆ๋‹ค ํ—ค๋”๋ฅผ ๊ฐ€์ง€๋ฉฐ ํ™”๋ฉด ๋ณ€๊ฒฝ๊ณผ ํ•จ๊ป˜ ๋‚˜ํƒ€๋‚˜๊ฑฐ๋‚˜ ์‚ฌ๋ผ์ง„๋‹ค.
  • none : ํ—ค๋”๊ฐ€ ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค.
<Stack.Screen 
    name="Home" 
    component={Home} 
    ooptions={{ headerShown: false }}
/>

headerShown ์€ ํ™”๋ฉด ์˜ต์…˜์œผ๋กœ, Navigator ์ปดํฌ๋„ŒํŠธ์˜ screenOptions์— ์„ค์ •ํ•˜๋ฉด ์ „์ฒด ํ™”๋ฉด์˜ ํ—ค๋”๊ฐ€ ๋ณด์ด์ง€ ์•Š๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

3. ํƒญ ๋‚ด๋น„๊ฒŒ์ด์…˜

  • ํ™”๋ฉด ์œ„๋‚˜ ์•„๋ž˜์— ์œ„์น˜ํ•˜๋ฉฐ, ํƒญ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋ฒ„ํŠผ๊ณผ ์—ฐ๊ฒฐ๋œ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.
  • ํƒญ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•œ๋‹ค.
npm install @react-navigation/bottom-tabs

 

ํ™”๋ฉด ๊ตฌ์„ฑ

src/navigations/Tab.js

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>
    );
};
  • createBottomTabNavigator ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ํƒญ ๋‚ด๋น„๊ฒŒ์ด์…˜์„ ์ƒ์„ฑ
  • ํƒญ ๋ฐ”์— ์žˆ๋Š” ๋ฒ„ํŠผ ์ˆœ์„œ๋Š” Navigator ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹์œผ๋กœ ์žˆ๋Š” Screen ์ปดํฌ๋„ŒํŠธ์˜ ์ˆœ์„œ์™€ ๋™์ผํ•˜๋‹ค.
  • ํƒญ ๋ฒ„ํŠผ์˜ ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•œ ์ฑ„ ๋ Œ๋”๋ง๋˜๋Š” ์ฒซ ํ™”๋ฉด์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ initialRouteName ์†์„ฑ์„ ์ด์šฉํ•œ๋‹ค.

 

 

ํƒญ ๋ฐ” ์ˆ˜์ •ํ•˜๊ธฐ

 

๋ฒ„ํŠผ ์•„์ด์ฝ˜ ์„ค์ •

  • tabBarIcon์„ ์ด์šฉํ•ด ํƒญ ๋ฒ„ํŠผ์— ์•„์ด์ฝ˜์„ ๋ Œ๋”๋งํ•œ๋‹ค.
  • tabBarIcon์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋ฒ„ํŠผ์˜ ์•„์ด์ฝ˜์ด ๋“ค์–ด๊ฐˆ ์ž๋ฆฌ์— ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

 

const TabIcon = ({ name, size, color }) => {
    return <MaterialCommunityIcons name={name} size={size} color={color} />;
};

const Tab = createBottomTabNavigator();

const TabNavigation = () => {
    return(
        <Tab.Navigator initialRouteName="Settings">
            <Tab.Screen 
                name="Mail" 
                component={Mail} 
                options={{
                    tabBarIcon: props => TabIcon({ ...props, name: 'email '}),
                }}
            />
            <Tab.Screen 
                name="Meet" 
                component={Meet} 
                options={{
                    tabBarIcon: props => TabIcon({ ...props, name: 'video' }),
                }}    
            />
            <Tab.Screen 
                name="Settings" 
                component={Settings} 
                options={{
                    tabBarIcon: props => TabIcon({ ...props, name: 'settings' }),
                }}    
            />
        </Tab.Navigator>
    );
};
  • ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๋Š” Screen ์ปดํฌ๋„ŒํŠธ๋งˆ๋‹ค tabBarIcon์— MaterialCommunityIcons ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  • ๋งŒ์•ฝ Screen ์ปดํฌ๋„ŒํŠธ๋งˆ๋‹ค ํƒญ ๋ฒ„ํŠผ ์•„์ด์ฝ˜์„ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ํ•œ๊ณณ์—์„œ ๋ชจ๋“  ๋ฒ„ํŠผ์˜ ์•„์ด์ฝ˜์„ ๊ด€๋ฆฌํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ Navigator ์ปดํฌ๋„ŒํŠธ์˜ screenOptions ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

const TabNavigation = () => {
    return(
        <Tab.Navigator 
            initialRouteName="Settings"
            screenOptions={({ route }) => ({
                tabBarIcon: props => {
                    let name = '';
                    if(route.name === 'Mail') name = 'email';
                    else if (route.name === 'Meet') name = 'video';
                    else name = 'settings';
                    return TabIcon({ ...props, name });
                },
            })}    
        >
            <Tab.Screen name="Mail" component={Mail} />
            <Tab.Screen name="Meet" component={Meet} />
            <Tab.Screen name="Settings" component={Settings} />
        </Tab.Navigator>
    );
};
  • screenOptions์— ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” route๋ฅผ ์ด์šฉํ•œ๋‹ค.

 

 

๋ผ๋ฒจ ์ˆ˜์ •

 

๋ฒ„ํŠผ ์•„๋ž˜์— ๋ Œ๋”๋ง๋˜๋Š” ๋ผ๋ฒจ์€ Screen ์ปดํฌ๋„ŒํŠธ์˜ name๊ฐ’์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

 

const TabNavigation = () => {
    return(
        <Tab.Navigator 
            initialRouteName="Settings"
            tabBarOptions={{ labelPosition: 'beside-icon', showLabel: false }}    
        >
            <Tab.Screen 
                name="Mail" 
                component={Mail} 
                options={{
                    tabBarLabel: 'Inbox',
                    tabBarIcon: props => TabIcon({ ...props, name: 'email '}),
                }}
            />
  • ๋ผ๋ฒจ์€ tabBarLabel์„ ์ด์šฉํ•ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  • labelPosition์„ ์„ค์ •ํ•˜์—ฌ ๋ผ๋ฒจ์„ ๋ฒ„ํŠผ ์•„์ด์ฝ˜์˜ ์•„๋ž˜๊ฐ€ ์•„๋‹Œ ์•„์ด์ฝ˜ ์˜†์— ๋ Œ๋”๋ง๋˜๋„๋ก ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  • showLabel์„ ์ด์šฉํ•ด ํƒญ ๋ฐ”์—์„œ ๋ผ๋ฒจ์ด ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์Šคํƒ€์ผ ์ˆ˜์ •

 

ํƒญ ๋ฐ”์˜ ๋ฐฐ๊ฒฝ์ƒ‰์„ ์ˆ˜์ •ํ•ด๋ณด์ž.

const TabNavigation = () => {
  return (
    <Tab.Navigator
      initialRouteName="Settings"
      tabBarOptions={{
        labelPosition: 'beside-icon',
        showLabel: false,
        style: {
          backgroundColor: '#54b7f9',
          borderTopColor: '#ffffff',
          borderTopWidth: 2,
        },
        activeTintColor: '#ffffff',
        inactiveTintColor: '#cfcfcf',
      }}
    >
  • ํƒญ ๋ฐ”์˜ ์Šคํƒ€์ผ์€ tabBarOptions ์†์„ฑ์— style์˜ ๊ฐ’์œผ๋กœ ์Šคํƒ€์ผ ๊ฐ์ฒด๋ฅผ ์„ค์ •ํ•ด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ํƒญ ๋ฒ„ํŠผ์˜ ์•„์ด์ฝ˜ ์ƒ‰์€ ๊ฐ๊ฐ activeTintColor์™€ inactiveTintColor๋ฅผ ์ด์šฉํ•ด ์„ค์ • ๊ฐ€๋Šฅํ•˜๋‹ค.

 

const TabNavigation = () => {
    return(
        <Tab.Navigator 
            initialRouteName="Settings"
            tabBarOptions={{ 
                labelPosition: 'beside-icon', 
                showLabel: false,
                style: {
                    backgroundColor: '#54b7f9',
                    borderTopColor: '#ffffff',
                    borderTopWidth: 2,
                },
                activeTintColor: '#ffffff',
                inactiveTintColor: '#cfcfcf',
            }}    
        >
            <Tab.Screen 
                name="Mail" 
                component={Mail} 
                options={{
                    tabBarLabel: 'Inbox',
                    tabBarIcon: props => 
                    TabIcon({ 
                        ...props, 
                        name: props.focused ? 'email' : 'email-outline',
                    }),
                }}
            />
     ...
  • ์•„์ด์ฝ˜์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ size, color, focused๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค.
  • ์ด ๊ฐ’์„ ์ด์šฉํ•ด ๋ฒ„ํŠผ์˜ ํ™œ์„ฑํ™” ์ƒํƒœ์— ๋”ฐ๋ฅธ ๋‹ค๋ฅธ ๋ฒ„ํŠผ์„ ๋ Œ๋”๋งํ•˜๊ฑฐ๋‚˜ ์Šคํƒ€์ผ๋ง์„ ๋ณ€๊ฒฝํ•œ๋‹ค.
  • focused์˜ ๊ฐ’์— ๋”ฐ๋ผ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™” ๋˜์—ˆ์„ ๋•Œ ๋‚ด๋ถ€๊ฐ€ ์ฑ„์›Œ์ง„ ์ด๋ฏธ์ง€๊ฐ€ ๋ Œ๋”๋ง๋œ๋‹ค.
  • ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ์—์„œ๋Š” ๋‚ด๋ถ€๊ฐ€ ๋นˆ ์•„์ด์ฝ˜์ด ๋ Œ๋”๋ง๋œ๋‹ค.

 


 

๋‚ด๋น„๊ฒŒ์ด์…˜์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๊ธฐ ์ „์— ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•  ์ง€ ๋ฏธ๋ฆฌ ๊ณ„ํš์„ ์„ธ์šฐ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋ฆฌ์•กํŠธ ๋‚ด๋น„๊ฒŒ์ด์…˜์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๋‚ด๋น„๊ฒŒ์ด์…˜์ด ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์–‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋„๋ก ํ•˜์ž.

๋Œ“๊ธ€