Chapter12 React Native Navigation 추가 설명.
React Native Expo의 활용성이 더욱 커지고 있습니다. 이전 Expo에서는 외부의 API를 쓸 수 없어서 효용 가치가 떨어졌지만 여러 라이브러리를 종합하여 쓰는 현 생태계에서 버전에 맞도록 버그없이 설치한다는 것은 어렵고 불편한 일입니다. 그렇지만 Expo insall (API)
와 같은 명령어를 통해 yan add (API)
를 쓰는 것과 같이 설치하면 버전을 Expo에서 맞추어 설치하여 주기 때문에 Warning 없이 설치되는 것은 아직 React-Native 초보인 저는 더 편하였습니다.
다만, 외부 API를 쓸 수 없다는 것은 단점으로 느껴졌으나 Expo를 Reject하지 않고 Expo-Kit를 이용하면 외부 API도 쓸 수 있도록 발전하고 있는 것에 대해서는 점점 더 코딩이 좋아지는 계기가 되고 있고 앞선 글에서 말씀드렸듯이 Expo로, React-Native를 이용하여 코드를 짜면 iOS / Android / Web 모두 쓸 수 있는 것은 정말 편한 일이라 생각합니다. 또한, React-Native의 stack navigator와 React Navigation의 stck navigator의 큰 차이점 중 하나로는 Stack의 경로 사이를 탐색할 때 Android, IOS에서 예상되는 제스처 및 애니메이션을 제공한다는 점에 있습니다.
이제 다시 Login Part로 넘어가서 하나씩 살펴보도록 하겠습니다. 이번시간에 정리할 내용은 Navigation의 추가 설명으로 아래와 같습니다.
- Navigation Tab Icon(createBottomTabNavigator)
- createStackNavigator
- Navigation Header
- Navigation Back title
Navigation Tab Icon(createBottomTabNavigator)
createBottomTabNavigator
인 BattomTabNavigator에서 여러 옵션들을 통해서 아이콘과 텍스트를 보여주게 할 수도 변경할 수도 있습니다. 또한, tabBarIcon
이라는 옵션을 통해 포커스 되었을 때 사용자가 해당 탭에 있다는 효과를 주기 위하여 색을 바꿀 수도 있습니다.
tabBarIcon Function that given { focused: boolean, color: string, size: number } returns a React.Node, to display in the tab bar.
여기서 focused 값을 이용하여 현재 선택된 tab의 value로써 boolean 값을 받았을 때 선택된 Tab의 색상을 지정할 수 있습니다. 그렇다면 사용법을 먼저 알아봅시다. BottomTabNavigator에 Icon을 추가하기 위하여 NavIcon이라는 Component를 추가합니다.
prismagram-app/components/NavIcon.js
import React from "react";
import { Ionicons } from "@expo/vector-icons";
import PropTypes from "prop-types";
import styles from "../styles";
const NavIcon = ({
focused = true,
name,
color = styles.blackColor,
size = 30
}) => (
<Ionicons
name={name}
color={focused ? color : styles.darkGreyColor}
size={size}
/>
);
NavIcon.propTypes = {
name: PropTypes.string.isRequired,
color: PropTypes.string,
size: PropTypes.number,
focused: PropTypes.bool
};
export default NavIcon;
이를 통해 expo vector icons list에서 Ionicons 카테고리의 아이콘을 BottomTabNavigator에 추가할 수 있는 컴포넌트를 만들었습니다. 이 컴포넌트의 속성으로 createBottomTabNavigator
의 옵션에 있는 값인 focused와 color, size를 변경하고자 합니다. 다시 createBottomTabNavigator로 돌아가면
navigations/TabNavigation.js
// 생략
export default createBottomTabNavigator(
{
Home: {
screen: stackFactory(Home, {
title: "Home",
headerRight: () => <MessagesLink />,
headerTitle: () => (
<Image style= resizeMode="contain" source={LOGO} />
)
}),
navigationOptions: {
tabBarIcon: ({ focused }) => (
<NavIcon
focused={focused}
name={Platform.OS === "ios" ? "ios-home" : "md-home"}
/>
)
}
},
createBottomTabNavigator에 Home Screen을 추가하고 navigationOptions으로 tabBarIcon이 focused 되었을 때 값을 NavIcon에 전달하기 위해서 prop으로 받아옵니다. 그런 후 TabBar 아이콘을 아까 만들어둔 NavIcon을 통해 설정합니다. React-Native의 Platform 컴포넌트로 ios일 때는 ios-home 아이콘을, ios가 아닐 때에는 md-home 아이콘으로 설정할 수 있습니다.
{
initialRouteName: "Notifications",
tabBarOptions: {
showLabel: false,
style: {
backgroundColor: "#FAFAFA"
}
}
}
);
그리고 바로 아래에 tabBarOptions를 통하여 tabBar의 배경 색상을 지정할 수 있습니다. 자, 여기까지가 TabNavigator의 색상을 지정하는 것이었습니다. 참고로 showLabel은 bottomTabBar에서 텍스트를 함께 보여줄 것인지 여보를 나타내는 것입니다. 만약 showLaber: true,
로 설정하게 되면 home 아이콘과 함께 “home”이라는 텍스트도 함께 나타나게 됩니다.
stackNavigator
Nomard Coder는 TabNavigor.js
안에 같이 두었습니다. 코드는 아래와 같습니다.
const stackFactory = (initialRoute, customConfig) =>
createStackNavigator(
{
InitialRoute: {
screen: initialRoute,
navigationOptions: {
...customConfig
}
},
Detail: {
screen: Detail,
navigationOptions: {
headerBackTitle: noContext,
title: "Photo"
}
},
UserDetail: {
screen: UserDetail,
navigationOptions: ({ navigation }) => ({
title: navigation.getParam("username")
})
}
},
{
defaultNavigationOptions: {
headerBackTitle: noContext,
headerTintColor: styles.blackColor,
headerStyle: { ...stackStyles }
}
}
);
이렇게 createStackNavigator를 stckFactory라는 변수로 지정하여 BottomTabNavigator를 지정할 때 함께 추가하였습니다. 즉, BottomTabNavigator로 해당 화면을 클릭하여 들어갈 때 stackNavigator도 함께 동작하게 됩니다. 이 부분은 바로 위 코드의
navigations/TabNavigation.js
// 생략
export default createBottomTabNavigator(
{
Home: {
screen: stackFactory(Home, {
title: "Home",
headerRight: () => <MessagesLink />,
headerTitle: () => (
<Image style= resizeMode="contain" source={LOGO} />
)
}),
navigationOptions: {
tabBarIcon: ({ focused }) => (
<NavIcon
focused={focused}
name={Platform.OS === "ios" ? "ios-home" : "md-home"}
/>
)
}
},
이 부분에서 screen: stackFactory(Home, {})
과 같습니다. 이렇게 하여 react-Navigator의 stack Navigator를 통해 gesture를 제공하게 되며 title을 넣을 수 있도록 합니다. 다만 stack Navigator에서 bottomTabNavigator에 등록되지 않은 navigation으로 들어갈 때는 backTitle(뒤로가기) 버튼이 텍스트와 함께 생기게 됩니다. 이 부분을 지우고 싶을 때는
const stackFactory = (initialRoute, customConfig) =>
createStackNavigator(
{
// ... 생략
},
{
defaultNavigationOptions: {
headerBackTitle: noContext,
headerTintColor: styles.blackColor,
headerStyle: { ...stackStyles }
}
}
);
defaultNavigationOptions으로 위와같이 설정하면 됩니다. Nomard Coder는 headerBackTitle을 null로 지정하였으나 어찌된 영문인지 저에게는 정상적으로 동작하지 않아서 또다른 value인 noContext를 지정해주었더니 잘 동작하였습니다. 참고하시어 진행하면 좋을 듯 합니다.
MessagesLink(createStackNavigator)
인스타그램을 보시면 상단 헤더의 우측 편에 메세지 링크로 보내는 아이콘이 존재합니다. 우선 이 부분은 TabNavigation.js
부분에서 아래와 같이 타이틀에 컴포넌트를 연결 시켜 줍니다.
import MessagesLink from "../components/AddPostLink";
//.. 기타 코드 중략
export default createBottomTabNavigator(
{
Community: {
screen: stackFactory(Community, {
title: "Community",
headerRight: () => <MessagesLink />,
headerTitle: () => (
<Image style= resizeMode="contain" source={LOGO} />
)
}),
navigationOptions: {
tabBarIcon: ({ focused }) => (
<NavIcon
focused={focused}
name={Platform.OS === "ios" ? "ios-chatbubbles" : "md-chatbubbles"}
/>
)
}
},
}
위와 같이 createStackNavigationOption으로 headerRight를 컴포넌트로 연결합니다. 그럼 컴포넌트에서 자세한 내용을 담아보겠습니다.
components/MessagesLink.js
import React from "react";
import { Platform } from "react-native";
import styled from "styled-components";
import { Ionicons } from "@expo/vector-icons";
import { withNavigation } from "react-navigation";
import styles from "../styles";
import NavIcon from "./NavIcon";
const Container = styled.TouchableOpacity`
padding-right: 20px;
`;
export default withNavigation(({ navigation }) => (
<Container onPress={() => navigation.navigate("MessageNavigation")}>
<NavIcon
name={Platform.OS === "ios" ? "ios-paper-plane" : "md-paper-plane"}
/>
</Container>
));
이 부분이 컴포넌트 부분입니다. 먼저 벡터 아이콘 컴포넌트인 NavIcons을 통해서 아이콘을 TouchableOpacity
로 감싸주어 해당 아이콘이 눌려 졌을 때 MEssageNavigation으로 보내도록 설정합니다. 이렇게 간단하게 헤더 부분에 아이콘을 넣어 다른 네비게이션으로 보낼 수 있습니다.
한가지 더 응용을 하면 이런 부분을 스크린에 직접 어떠한 버튼을 넣었을 때 TouchableOpacity
로 감싸 주어 navigation.navigate("원하는스크린")
로 보내주기만 하면 이동을 할 수 있습니다. 이처럼 매우 간편한 네이게이션 편이었습니다.
Leave a comment