티스토리 뷰

우리가 자주 사용하는 Youtube 앱을 보면 하단 탭이 다음처럼 구성되어 있다.

여기서 가운데에 있는 + 아이콘을 누르면 다음과 같은 모달창이 나타난다.

이와 같은 기능을 React Navigation 을 통해 구현해보겠다.

준비사항

"@react-navigation/bottom-tabs": "^6.2.0",
"@react-navigation/native": "^6.0.8",
"@react-navigation/stack": "^6.2.1",
"react-native-modal": "^13.0.1",

구현을 위해 위 라이브러리들이 필요하다 npm 혹은 yarn 을 이용해 설치하자.

결과물

먼저 완성된 결과물을 먼저 보자.

홈화면은 다음과 같이 이루어져있다. 이곳에서 하단의 등록 메뉴를 클릭하면

이런 모달이 나타나게 된다.

우리 서비스의 경우에는 분실신고 를 클릭했을 때 분실신고 작성 폼 으로 이동하도록 했다.

이렇게 별도의 폼으로 이동하게 된다.

구현

먼저 하단 탭 네비게이션을 만들어야 한다.

전체 소스코드는 다음과 같다.

<Tab.Navigator
      initialRouteName="홈"
      screenOptions={{
        tabBarActiveTintColor: '#F5BA25',
        tabBarInactiveTintColor: '#595959',
        headerShown: false,
        tabBarLabelStyle: { fontSize: 14 },
        tabBarStyle: {
          height: hp('10%'),
          position: 'absolute',
        },
      }}>
      <Tab.Screen
        name="홈"
        component={Home}
        options={{
          tabBarIcon: ({ color, size, focused }) =>
            focused ? (
              <IIcon name="ios-home-sharp" color={color} size={size} />
            ) : (
              <IIcon name="ios-home-outline" color={color} size={size} />
            ),
        }}
      />
      <Tab.Screen
        name="지역"
        component={Map}
        options={{
          tabBarIcon: ({ color, size, focused }) =>
            focused ? (
              <MCIcon name="map-marker" color={color} size={size} />
            ) : (
              <MCIcon name="map-marker-outline" color={color} size={size} />
            ),
        }}
      />
      <Tab.Screen
        name="등록"
        component={ReportModal}
        listeners={() => ({
          tabPress: e => {
            e.preventDefault();
            navigation.navigate('reportModal');
          },
        })}
        options={{
          tabBarIcon: ({ color, size, focused }) =>
            focused ? (
              <MCIcon name="plus-circle" color={color} size={size} />
            ) : (
              <MCIcon name="plus-circle-outline" color={color} size={size} />
            ),
        }}
      />
      <Tab.Screen
        name="의뢰"
        component={Detective}
        options={{
          tabBarIcon: ({ color, size, focused }) =>
            focused ? (
              <MCIcon name="shield-crown" color={color} size={size} />
            ) : (
              <MCIcon name="shield-crown-outline" color={color} size={size} />
            ),
        }}
      />
      <Tab.Screen
        name="더보기"
        component={More}
        options={{
          tabBarIcon: ({ color, size }) => (
            <MIcon name="more-horiz" color={color} size={size} />
          ),
        }}
      />
    </Tab.Navigator>

여기서 자세히 봐야할 부분은 등록 부분이다.

listeners={() => ({
  tabPress: e => {
    e.preventDefault();
    navigation.navigate('reportModal');
  },
})}

잘 보면 listeners 속성에 있는 tabPress 의 수정해주었다.
기존대로라면 등록버튼을 클릭할때, 해당 컴포넌트가 렌더링 되야 할 것이다.
하지만 우리가 원하는 동작은 새로운 컴포넌트가 렌더링이 되는것이 아닌 기존 화면에서 모달창만 튀어나오게 하는 것이다. 따라서 e.preventDefault() 를 통해 기본동작을 제거하고 navigate 함수를 통해 화면을 이동하게 했다.

이제 어떻게 저 navigate 함수가 동작하는지 보자.

App.tsx 에서 다음과 같이 Stack Navigator를 구성했다.

<NavigationContainer>
  <Stack.Navigator screenOptions={{ headerShown: false }}>
    <Stack.Screen name="main" component={MainNavigation} />
    <Stack.Screen name="lostReportStack" component={LostReportStack} />
    <Stack.Group screenOptions={{ presentation: 'transparentModal' }}>
      <Stack.Screen
        name="reportModal"
        component={ReportModal}
        options={{
          animationEnabled: false,
        }}
      />
    </Stack.Group>
  </Stack.Navigator>
</NavigationContainer>

여기서 <Stack.Screen name="lostReportStack" component={LostReportStack} /> 부분은
위 결과물에서 분실신고 를 눌렀을 때 나오는 작성 폼에대한 스택이므로 신경쓰지 않아도 된다.

주의 깊게 봐야 할 부분은 이 부분이다.

<Stack.Group screenOptions={{ presentation: 'transparentModal' }}>
  <Stack.Screen
    name="reportModal"
    component={ReportModal}
    options={{
      animationEnabled: false,
    }}
  />
</Stack.Group>

이렇게 Stack.Group 에 있는 screenOptions 설정을 통해 해당 화면을 Modal화면으로 만들 수 있다.
또한, 기존에 렌더링 되어있던 화면을 유지시키기 위해서는 { presentation: 'transparentModal' } 속성을 적용해야 한다.

그 후에 만들어놓은 Modal 컴포넌트를 등록시켜놓으면 아까 위에서 봤던 navigation.navigate('reportModal') 함수가 불렸을 때 해당 스택이 렌더링되는 것이다.

정리

  • React Navigation의 Stack.Group에 존재하는 Modal속성을 이용하자.
  • 기존 화면에 모달이 나타나게 하려면 transparentModal 속성을 주자.
  • 탭네비게이션을 하나의 스택으로, 모달을 하나의 스택으로 구성하여 navigate 함수를 통해 전환이 가능하게 하자. 이렇게하면 여러가지 스택 확장이 가능하며 각 스택에서 홈 화면으로 이동하는 것이 가능하다.

'ReactNative' 카테고리의 다른 글

[ReactNative] iOS 디바이스 테스트하기  (0) 2022.04.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함