티스토리 뷰
[ReactNative] React Navigation BottomTab Modal 만들기 (유튜브 하단 탭 기능 구현하기)
jonyo 2022. 4. 7. 13:51우리가 자주 사용하는 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
- 동적계획법
- 투포인터
- node.js
- 세그먼트 트리
- 벨만포드
- typeORM
- 컴퓨터 통신
- 예외처리
- 그리디
- 백트래킹
- BFS
- dfs
- 중앙대학교
- ReactNative
- 컴퓨터 구조
- java
- 백준
- Computer Architecture
- 재귀
- nodeJS
- 스레드
- 시뮬레이션
- nestjs
- 자바
- 알고리즘
- 자바스크립트
- nest.js
- 구현
- boj
- 그래프
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |