[react-native] Tab Navigation

    반응형
    이 글은 <처음 배우는 리액트 네이티브 (김범준, 한빛미디어)>를 읽고 이해한 바를 바탕으로 작성되었습니다.
     

    GitHub - Alchemist85K/my-first-react-native: [한빛미디어] 처음 배우는 리액트 네이티브 소스 코드입니다.

    [한빛미디어] 처음 배우는 리액트 네이티브 소스 코드입니다. . Contribute to Alchemist85K/my-first-react-native development by creating an account on GitHub.

    github.com

     

    💡 탭 내비게이션

    탭 내비게이션은 보통 화면 위나 아래에 위치해서 탭 버튼을 누르면 버튼과 연결된 화면으로 이동하는 방식으로 동작한다.

    카카오톡, 인스타그램, 유튜브 등 많은 앱들이 탭 내비게이션을 사용하고 있다.

     

    인스타그램도 탭내비게이션!

     

    ✔️ 탭 내비게이션을 사용하기 위한 추가 라이브러리를 설치한다.

    npm install @react-navigation/bottom-tabs

     

    💡 화면 구성

    ✅ src/screens/TabScreen.js

    import React from 'react';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        flex: 1;
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
    `;
    
    export const Mail = () => {
        return (
            <Container>
                <StyledText>Mail</StyledText>
            </Container>
        )
    };
    
    export const Meet = () => {
        return (
            <Container>
                <StyledText>Meet</StyledText>
            </Container>
        )
    };
    
    export const Settings = () => {
        return(
            <Container>
                <StyledText>Settings</StyledText>
            </Container>
        )
    };
    
    /* src/screens/TabScreen.js */

    Mail, Meet, Settings 3가지 Screen 컴포넌트들을 생성하였다.

     

    ✅ src/navigations/Tab.js

    import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    import { Mail, Meet, Settings } from '../screens/TabScreen';
    
    const Tab = createBottomTabNavigator();
    
    const TabNavigation = () => {
        return (
            <Tab.Navigator>
                <Tab.Screen name='Mail' component={Mail} />
                <Tab.Screen name='Meet' component={Meet} />
                <Tab.Screen name='Settings' component={Settings} />
            </Tab.Navigator>
        );
    };
    
    export default TabNavigation;
    
    /* src/navigations/Tab.js */

    createBottomTabNavigator()함수를 이용해서 Navigator 컴포넌트를 생성한 후, 3가지 Screen 컴포넌트들을 Navigator 컴포넌트의 자식 컴포넌트들로 작성하였다.

     

    ✅ src/App.js

    import React from 'react';
    import { NavigationContainer } from '@react-navigation/native';
    import TabNavigation from './navigations/Tab';
    
    const App = () => {
        return (
            <NavigationContainer>
                <TabNavigation />
            </NavigationContainer>
        )
    }
    
    export default App;
    
    /* src/App.js */

    NavigationContainer 컴포넌트로 Navigator 컴포넌트를 감싸준다.

     

    이렇게 3가지 Screen 컴포넌트를 가지는 탭내비게이션이 만들어진다!

     

    탭 바에서의 Screen 컴포넌트의 순서를 변경하고 싶다면, Navigator 컴포넌트 안에 작성해준 자식 Screen 컴포넌트들의 순서를 변경해주고,

    첫 화면으로 사용하고 싶은 컴포넌트를 명시할 때에는 Navigator 컴포넌트의 initialRouteName속성으로 첫 화면에 사용하고 싶은 Screen 컴포넌트의 name을 직접 명시해준다.

    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>
        );
    };
    
    /* src/navigations/Tab.js */

    첫 화면은 Settings로 설정하였고, 자식 Screen 컴포넌트의 순서를 Mail이 첫번째에 오도록 변경해주었다.

     

     

    💡 탭 바 수정하기

    ✔️ 버튼 아이콘 설정하기

    위에서는 탭 버튼 아이콘이 지정되어 있지 않은 모습이다.

    탭 버튼 아이콘은 tabBarIcon을 이용해서 렌더링해줄 수 있다. 

    tabBarIcon에 아이콘을 렌더링하는 컴포넌트를 반환하는 함수를 지정한다.

     

    1. Screen 컴포넌트마다 tabBarIcon 지정하기

    import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    import { Mail, Meet, Settings } from '../screens/TabScreen';
    import { MaterialCommunityIcons } from '@expo/vector-icons';
    
    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: 'cog'})
                    }}
                    />
            </Tab.Navigator>
        );
    };
    
    
    
    export default TabNavigation;
    
    /* src/navigations/Tab.js */

     

    2. Navigator 컴포넌트의 screenOptions 속성으로 설정하기

    import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    import { Mail, Meet, Settings } from '../screens/TabScreen';
    import { MaterialCommunityIcons } from '@expo/vector-icons';
    
    const TabIcon = ({ name, size, color }) => {
        return <MaterialCommunityIcons name={name} size={size} color={color} />;
    };
    
    const Tab = createBottomTabNavigator();
    
    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 = 'cog';
                        return TabIcon({...props, name});
                    },
                })}
                >
                <Tab.Screen name='Mail' component={Mail} />
                <Tab.Screen name='Meet' component={Meet}/>
                <Tab.Screen name='Settings' component={Settings} />
            </Tab.Navigator>
        );
    };
    
    export default TabNavigation;
    
    /* src/navigations/Tab.js */

    Navigator 컴포넌트에서 screenOptions에 객체를 반환하는 함수에 route를 넘긴다.

    Screen 컴포넌트의 name속성을 값으로 갖는 route의 name값에 따라 아이콘이 렌더링되도록 작성하였다.

    두가지 방법 모두 결과는 동일하다.

     

    ✔️ 라벨값 수정하기

    버튼 아이콘 아래에 렌더링되는 라벨은 Screen 컴포넌트의 name 값을 기본값으로 사용한다.

    기본값을 사용하지 않고 원하는 값으로 변경하기 위해서는 tabBarLabel을 이용하여 변경할 수 있다.

    ...
    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
                >
                <Tab.Screen 
                    name='Mail'
                    component={Mail}
                    options = {{
                        tabBarLabel: 'Inbox',
                        tabBarIcon: props => TabIcon({...props, name: 'email'}),
                    }}
                    />
                <Tab.Screen name='Meet' component={Meet}/>
                <Tab.Screen name='Settings' component={Settings} />
            </Tab.Navigator>
        );
    };
    ...
    
    /* src/navigations/Tab.js */

    Mail Screen 컴포넌트의 라벨을 'Inbox'로 명시해주었다.

    라벨을 Inbox로 변경

     

    ✔️ 라벨 위치 수정하기

    라벨의 위치는 labelPosition의 값으로 변경할 수 있고, labelPosition으로 지정할 수 있는 값은 below-icon과 beside-icon 두가지이다.

    ...
    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
                tabBarOptions={{ labelPosition: 'beside-icon' }}
                ...
                >
                <Tab.Screen
                    ...
                />
            </Tab.Navigator>
        );
    };
    ...
    
    /* src/navigations/Tab.js */

    Navigator 컴포넌트의 속성으로 tabBarOptions에서 labelPosition을 'beside-icon'으로 지정해주었다.

    아이콘 오른쪽으로 라벨 위치 수정

    ✔️ 라벨 숨기기

    ...
    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
                tabBarOptions={{ labelPosition: 'beside-icon', showLabel: false }}
                ...
                >
                <Tab.Screen
                    ...
                />
            </Tab.Navigator>
        );
    };
    ...
    
    /* src/navigations/Tab.js */

    showLable의 값을 'false'로 지정하여 라벨을 숨길 수 있다.

    라벨 숨김

     

    ✔️ 스타일 수정하기 - 내비게이션 스크린 배경색과 탭 바 배경색 변경하기

    탭 내비게이션의 탭 바 배경색은 흰색이 디폴트값이다. 

    탭 바의 스타일을 수정하기 위해서는 앞에서도 사용했던 screenOptions에서 tabBarStyle로 스타일링을 해줄 수 있다.

    ((

    책에서는 screenOptions말고 tabBarOptions에서 style에서 스타일링을 해주는데 이렇게 하면 나는 안되고 에뮬레이터에서 경고창이 뜬다. 그래서 screenOptions에서 스타일링을 해주었다! 이렇게 해주면 잘 스타일링된다!

    ))

    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
                screenOptions={({ route }) => ({
                    tabBarIcon: props => {
                        ...
                    },
                    tabBarStyle: {
                        backgroundColor: '#2A3D66',
                        borderTopColor: '#ffffff',
                        borderTopWidth: 1,
                    }
                })}
                >
                <Tab.Screen 
                	...    
                />
            </Tab.Navigator>
        );
    };

    탭내비게이션 스크린 배경색이랑 탭바 배경색 변경

     

    ✔️ 스타일 수정하기 - 탭 버튼 아이콘 스타일링

    마찬가지로 screenOptions에서 수정해주는데, 탭 버튼 아이콘이 활성화되어있을 때와 활성화되어있지 않을 때 색을 다르게 적용하기 위해서 tabBarActiveTintColor의 값과 tabBarInactiveTintColor의 값을 지정해주었다.

    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
                screenOptions={({ route }) => ({
                    tabBarIcon: props => {
                        ...
                    },
                    tabBarStyle: {
                        ...
                    },
                    tabBarActiveTintColor: '#ffffff',
                    tabBarInactiveTintColor: '#93B5C6',
                })}
                >
                <Tab.Screen 
                	...    
                />
            </Tab.Navigator>
        );
    };

    아이콘 색상 변경

     

    ✔️ 스타일 수정하기 - 버튼 선택 상태에 따라 다른 버튼 렌더링 + 다른 스타일링

    앞에서 각각의 스크린 컴포넌트에서 tabBarIcon버튼 아이콘을 각각 지정해주었다.

    tabBarIcon에 설정한 함수에는 파라미터로 size, color, focused를 객체로 전달한다.

    여기서 focused는 버튼의 선택된 상태를 나타내는 값인데, 이 값을 통해서 버튼이 활성화 되었을 때와 그렇기 않을 때 각각 다른 버튼을 렌더링해보겠다.

    ...
    
    const TabNavigation = () => {
        return (
            <Tab.Navigator
                ...
            >
                <Tab.Screen 
                    name='Mail'
                    component={Mail}
                    options = {{
                        tabBarIcon: props =>
                            TabIcon({
                                ...props,
                                name: props.focused ? 'email' : 'email-outline',
                            }),
                    }}
                    />
                <Tab.Screen 
                    name='Meet'
                    component={Meet}
                    options = {{
                        tabBarIcon: props =>
                            TabIcon({
                                ...props,
                                name: props.focused ? 'video' : 'video-outline',
                            }),
                    }}
                    />
                <Tab.Screen
                    name='Settings'
                    component={Settings}
                    options = {{
                        tabBarIcon: props =>
                            TabIcon({
                                ...props,
                                name: props.focused ? 'cog' : 'cog-outline',
                            }),
                    }}
                    />
            </Tab.Navigator>
        );
    };
    
    export default TabNavigation;
    
    /* src/navigations/Tab.js */

     

    각각의 스크린 컴포넌트의 tabBarIcon에서 조건문으로 버튼이 활성화되었을 때에는 내부가 채워진 이미지로. 비활성화되었을 때에는 테두리만 있는 이미지로 렌더링되도록 한다.

    짠✨

     

    반응형

    댓글