들어가기
insta에서 사용되는 page들의 nav를 마지막으로 정리함.
nav에 nav가 들어가고 복잡하지만, 집중해서 머릿속에 깔끔하게 정리할 것.
LoggedOutNav는 정리에서 생략함.
기본적으로 StackNav
Screen에 TabsNav(Nav), UploadNav(Nav), UploadForm(Screen)
3개를 Stack으로 배치함.
import { createStackNavigator } from '@react-navigation/stack'
import UploadForm from '../screens/UploadForm'
import TabsNav from './TabsNav'
import UploadNav from './UploadNav'
import { Ionicons } from '@expo/vector-icons'
const Stack = createStackNavigator()
export default function LoggedInNav() {
return (
<Stack.Navigator presentation="modal">
<Stack.Screen
name="Tabs"
options={{ headerShown: false }} ***=>여기서도 Nav의 options가능함.
component={TabsNav}
/>
<Stack.Screen
name="Upload"
options={{ headerShown: false }} ***=>여기서도 Nav의 options가능함.
component={UploadNav}
/>
///uploadNav(selectPhoto, takePhoto에서 고르거나, 찍은 사진을
///upload하는 Screen은 loggedInNav의 stack에 넣어줌.
<Stack.Screen
name="UploadForm"
options={{
headerBackTitleVisible: false,
headerBackImage: ({ tintColor }) => (
<Ionicons name="close" color='white' size={28} />
),
///headerBacKImage는 함수로 Ionicons를 넣어주는것도 가능함.
///자세한 options들은 공식문서 참고할 것!
title: 'Upload',
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'black',
},
}}
component={UploadForm}
/>
</Stack.Navigator>
)
}
sharedStackNav와 같이 봐야 이해가 되는 Nav임.
하단의 5개의 tab을 클릭하게 되면, StackNav로 넘어가서
클릭된 tab과 sharedStackNav에 있는 Profile, Photo, Comments, Likes와
Stack으로 쌓이는 구졸호 설정됨.
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import React from 'react'
import { Ionicons } from '@expo/vector-icons'
import { Image, View } from 'react-native'
import SharedStackNav from './SharedStackNav'
import useMe from '../hooks/useMe'
const Tabs = createBottomTabNavigator()
export default function TabsNav() {
const { data } = useMe()
return (
<Tabs.Navigator
screenOptions={{
headerShown: false,
tabBarShowLabel: false,
tabBarStyle: {
backgroundColor: 'black',
borderTopColor: 'rgba(255,255,255,0.5)',
},
tabBarActiveTintColor: 'white',
}}
>
<Tabs.Screen
name="tabFeed"
options={{
///tabBarIcon을 Ionicons로 설정하는 방법 check할것!!
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="home" color={color} size={focused ? 24 : 20} />
),
}}
>
{() => <SharedStackNav screenName="Feed" />}
///home icon을 누르게 되면, SharedStackNav로 넘어가게됨.
///screenName로 이름을 넘겨주고, sharedStackNav에서 screenName으로 받음.
</Tabs.Screen>
<Tabs.Screen
name="tabSearch"
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="search" color={color} size={focused ? 24 : 20} />
),
}}
>
{() => <SharedStackNav screenName="Search" />}
</Tabs.Screen>
<Tabs.Screen
name="tabCamera"
component={View}
///가운데의 camera icon을 클릭했을 때, listeners를 이용하여,
///Uploadnav로 이동하게 함.
///navigation을 받아서 이동시키면 됨.
///e와 e.preventDefault()는 클릭시 event가 일어나지 않게 하는것.
///중요한부분이니, tabPress, listeners, navigation모두 check할 것!!
listeners={({ navigation }) => {
return {
tabPress: (e) => {
e.preventDefault()
navigation.navigate('Upload')
},
}
}}
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="camera" color={color} size={focused ? 24 : 20} />
),
}}
/>
<Tabs.Screen
name="tabMe"
options={{
tabBarIcon: ({ focused, color, size }) =>
data?.me?.avatar ? (
<Image
source={{ uri: data.me.avatar }}
style={{ height: 20, width: 20, borderRadius: 10 }}
/>
) : (
<Ionicons name="person" color={color} size={focused ? 24 : 20} />
),
}}
>
{() => <SharedStackNav screenName="Me" />}
</Tabs.Screen>
<Tabs.Screen
name="tabNotification"
options={{
tabBarIcon: ({ focused, color, size }) => (
<Ionicons name="heart" color={color} size={focused ? 24 : 20} />
),
}}
>
{() => <SharedStackNav screenName="Notification" />}
</Tabs.Screen>
</Tabs.Navigator>
)}
TabsNav에서 screenOption으로 screen을 보내면 그 screen을 받아서,
Profile, Photo, likes, Comments 4개의 스크린 위에 stack으로 쌓음.
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import Feed from '../screens/Feed'
import Search from '../screens/Search'
import Notification from '../screens/Notification'
import Me from '../screens/Me'
import Profile from '../screens/Profile'
import Photo from '../screens/Photo'
import { Image } from 'react-native'
import Comments from '../screens/Comments'
import Likes from '../screens/Likes'
const Stack = createStackNavigator()
export default function SharedStackNav({ screenName }) {
return (
<Stack.Navigator
screenOptions={{
headerBackTitleVisible: false,
headerTintColor: 'white',
headerStyle: {
shadowColor: 'rgba(255,255,255,0.3)',
backgroundColor: 'black',
},
tabBarShowLabel: false,
tabBarStyle: {
backgroundColor: 'black',
borderTopColor: 'rgba(255,255,255,0.5)',
},
tabBarActiveTintColor: 'white',
}}
>
{screenName === 'Feed' ? (
<Stack.Screen
name="Feed"
component={Feed}
options={{
headerTitle: () => (
<Image
style={{ width: 120, height: 40, marginLeft: 120 }}
resizeMode="cover"
source={require('../assets/logo.png')}
///header에 image를 넣을 수도 있음.
///예를들면, instagram logo같은 거
/>
),
}}
/>
) : null}
{screenName === 'Search' ? (
<Stack.Screen name="Search" component={Search} />
) : null}
{screenName === 'Notification' ? (
<Stack.Screen name="Notification" component={Notification} />
) : null}
{screenName === 'Me' ? <Stack.Screen name="Me" component={Me} /> : null}
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Photo" component={Photo} />
<Stack.Screen name="Comments" component={Comments} />
<Stack.Screen name="Likes" component={Likes} />
</Stack.Navigator>
)
}
loggedInNav에 stack.Screen으로 넣은 nav
createMaterialNavigator를 사용
https://reactnavigation.org/docs/material-top-tab-navigator
Tab과 Stack 두개를 사용한 이유는,
원래 Tab.screen으로 두 screen(selectPhoto, takePhoto)을
셋팅할 수 있으나, selectPhoto screen은 header에 다양한 설정을 하기 위해
Stack으로 다시 감싸줌.
loggedInNav에서 uploadNav는 headerShown:false로 설정됨.
TabNav안에 StackNav가 들어가는 경우도 잘 봐두면 좋을거 같음.
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'
import { createStackNavigator } from '@react-navigation/stack'
import React from 'react'
import SelectPhoto from '../screens/SelectPhoto'
import TakePhoto from '../screens/TakePhoto'
import { Ionicons } from '@expo/vector-icons'
const Tab = createMaterialTopTabNavigator()
const Stack = createStackNavigator()
export default function UploadNav() {
return (
<Tab.Navigator
tabBarPosition="bottom"
screenOptions={{
tabBarStyle: { backgroundColor: 'black' },
tabBarLabelStyle: { color: 'white' },
// tabBarActiveTintColor: { color:'black' },
}}
>
*************TanNav안에 StackNav가 들어가는 경우, 잘 봐둘것!!!!
<Tab.Screen name="Select_Photo">
{() => (
<Stack.Navigator
screenOptions={{
headerTintColor: 'white',
headerBackTitleVisible: false,
headerBackImage: ({ tintColor }) => (
<Ionicons color={tintColor} name="close" size={28} />
),
headerStyle: {
backgroundColor: 'black',
shadowOpacity: 0.3,
},
}}
>
<Stack.Screen
options={{ title: 'Choose a Photo!' }}
name="Select"
component={SelectPhoto}
/>
</Stack.Navigator>
)}
</Tab.Screen>
<Tab.Screen name="Take_Photo" component={TakePhoto} />
</Tab.Navigator>
)
}