navigation 정리

김종민·2022년 6월 7일
0

insta-native

목록 보기
24/36

들어가기
insta에서 사용되는 page들의 nav를 마지막으로 정리함.
nav에 nav가 들어가고 복잡하지만, 집중해서 머릿속에 깔끔하게 정리할 것.
LoggedOutNav는 정리에서 생략함.

  1. loggedInNav.js
  2. SharedStackNav.js
  3. TabsNav.js
  4. UploadNav.js

1. loggedInNav.js

기본적으로 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>
  )
}

2.TabsNav.js

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> 
    
    )}
    
 

3. sharedStackNav.js

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>
  )
}

  

4. uploadNav.js

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>
  )
}
profile
코딩하는초딩쌤

0개의 댓글