reactnavigation.org 의 Tab navigation 번역 자료입니다. 번역에 문제가 있다면 댓글 달아주시구요. 원문을 보시기를 추천드립니다
아마도 모바일 앱에서 가장 일반적인 네비게이션 스타일은 탭 기반 네비게이션 일 것입니다. 이것은 스크린 하단 또는 헤더 아래 (또는 헤더 대신)에 있는 탭일 수 있습니다.
이 가이드는 createBottomTabNavigator
에 대해 설명합니다. createMaterialBottomTabNavigator
및 createMaterialTopTabNavigator
를 사용하여 애플리케이션에 탭을 추가 할 수도 있습니다.
계속하기 전에 먼저 @react-navigation/bottom-tabs
를 설치하세요 :
npm
npm install @react-navigation/bottom-tabs
yarn
yarn add @react-navigation/bottom-tabs
탭 기반(tab-based) 네비게이션의 미니멀 예제
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
외관 커스터마이즈
스택 네비게이터를 커스터마이즈하는 방법과 유사합니다 - 탭 네비게이터를 초기화 할 때 설정되는 약간의 프로퍼티와 options
에서 스크린별로 커스터마이즈할 수 있는 프로퍼티가 있습니다.
// Expo를 사용하는 경우 @expo/vector-icons에서 Ionicons를 import 하거나
// 그렇지 않으면 react-native-vector-icons/Ionicons를 import 할 수 있습니다.
import { Ionicons } from '@expo/vector-icons';
// (...)
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// 여기에 원하는 컴포넌트를 반환 할 수 있습니다!
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
코드를 자세히 봅시다.
tabBarIcon
은 하단 탭 네비게이터에서 지원되는 옵션입니다. 스크린 컴포넌트에서options
prop을 사용할 수도 있지만 이 경우 편의를 위해 아이콘 구성을 모아Tab.Navigator
의screenOptions prop
에 넣었습니다.tabBarIcon
은focused
state,color
및size params
가 제공되는 함수입니다. 설정을 자세히 살펴보면tabBarOptions
및activeTintColor
및inactiveTintColor
를 보게됩니다. 기본값은 iOS 플랫폼 기본값이지만 여기에서 변경할 수 있습니다.tabBarIcon
에 전달되는color
는focused
state (focused is active)에 따라 활성 또는 비활성 색상입니다.size
는 탭바에서 예상되는 아이콘의 크기입니다.createBottomTabNavigator
설정 옵션에 대한 자세한 정보는 전체 API 레퍼런스를 읽으십시오.
아이콘에 배지 추가
때로는 아이콘에 배지를 추가하기를 원합니다. 일반적인 방법은 엑스트라 뷰 컨테이너를 사용하고 절대 위치(absolute positioning)로 배지 요소의 스타일을 지정하는 것입니다.
function IconWithBadge({ name, badgeCount, color, size }) {
return (
<View style={{ width: 24, height: 24, margin: 5 }}>
<Ionicons name={name} size={size} color={color} />
{badgeCount > 0 && (
<View
style={{
// React Native < 0.57에서는 부모 외부(outside of parent)의 오버플로우가 Android에서 작동하지 않습니다. https://git.io/fhLJ8
position: 'absolute',
right: -6,
top: -3,
backgroundColor: 'red',
borderRadius: 6,
width: 12,
height: 12,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>
{badgeCount}
</Text>
</View>
)}
</View>
);
}
UI 관점에서 이 컴포넌트는 사용할 준비가 되었지만 React Context, Redux, MobX 또는 event emitters를 사용하는 등의 다른 곳에서 배지 수를 올바르게 전달할 수있는 방법을 찾아야합니다.
function HomeIconWithBadge(props) {
// React Context API, Redux, MobX 또는 event emitters와 같은 다른 방법으로 badgeCount를 전달해야합니다.
return <IconWithBadge {...props} badgeCount={3} />;
}
탭 간 점프
한 탭에서 다른 탭으로 전환하는 익숙한 API - navigation.navigate
.
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}
각 탭의 스택 네비게이터
일반적으로 탭은 하나의 스크린만 표시하지 않습니다. 예를 들어 Twitter 피드에서 트윗을 탭하면 해당 탭 내에서 모든 답글이 포함 된 새 스크린이 나타납니다. 각 탭 내에 별도의 네비게이션 스택이 있다고 생각할 수 있습니다. 이것이 바로 React Navigation의 모델링 방식입니다.
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
왜 TabBarIOS 나 다른 컴포넌트 대신 TabNavigator가 필요합니까?
스탠드얼론 탭바 컴포넌트를 앱에서 사용하는 네비게이션 라이브러리에 통합하지 않고 사용하려고 시도하는 것이 일반적일 겁니다. 어떤 경우에는 이것이 잘 작동합니다! 그러나 이렇게하면 예상치 못한 문제가 발생할 수 있음을 경고해야합니다.
예를 들어, React Navigation의 탭 네비게이터는 Android back button을 처리하지만 스탠드얼론 컴포넌트는 일반적으로 처리하지 않습니다. 또한 두 개의 고유한 API를 호출해야하는 경우 (개발자로서) “이 탭으로 이동한 다음 이 화면으로 이동”과 같은 조치를 수행하기가 더 어렵습니다. 마지막으로, 모바일 유저 인터페이스에는 특정 컴포넌트가 다른 컴포넌트의 레이아웃 또는 존재를 인식해야 하는 수많은 작은 디자인 디테일이 있습니다. - 예를 들어, 반투명 탭바가 있는 경우 컨텐츠가 그 아래에서 스크롤되고 스크롤뷰의 맨 아래에 탭바의 높이와 동일한 삽입이 있어야 모든 컨텐츠를 볼 수 있습니다. 탭 표시 줄을 두 번 누르면 활성 네비게이션 스택이 스택의 상단으로 튀어 나와야(pop)하고 다시 수행하면 해당 스택의 활성 스크롤뷰가 맨 위로 스크롤됩니다. 이러한 모든 동작이 React Navigation으로 아직 구현되지는 않았지만 스탠드얼론 탭뷰 컴포넌트를 사용하면 이 중 아무것도 실행되지 않습니다.