개발조각

[React-native CLI] svg사용하는 방법 및 react-navigation 커스텀 본문

React-Native/[프로젝트] 택시 운행관리 기록장

[React-native CLI] svg사용하는 방법 및 react-navigation 커스텀

개발조각 2024. 3. 6. 00:08
728x90
반응형

react navigation을 아래의 화면같이 커스텀할 예정입니다.

디자인 화면을 보면 하단 내비게이션에 각 스크린별로 아이콘이 있는데 이 부분을 svg를 사용해서 구현할 예정입니다.

 

react native에서 svg사용하기


설치

npm install react-native-svg

 

폴더

app
|- assets
    |- svg.tsx
|- navigation
	|- BottomTabsNabvigator.tsx
    |- StackNavigator.tsx
|- screens
|- App.tsx

 

assets/svg.tsx

export const svg = {
  home: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="22" viewBox="0 0 24 22">
    <path d="M23.9937 11.1467C23.9937 11.8968 23.3687 12.4844 22.6603 12.4844H21.3268L21.356 19.1599C21.356 19.2724 21.3476 19.3849 21.3351 19.4974V20.1683C21.3351 21.0893 20.5893 21.8351 19.6683 21.8351H19.0016C18.9558 21.8351 18.9099 21.8351 18.8641 21.831C18.8058 21.8351 18.7474 21.8351 18.6891 21.8351H17.3348H16.3347C15.4138 21.8351 14.6679 21.0893 14.6679 20.1683V19.1683V16.5014C14.6679 15.7638 14.072 15.1679 13.3345 15.1679H10.6676C9.93001 15.1679 9.33413 15.7638 9.33413 16.5014V19.1683V20.1683C9.33413 21.0893 8.58823 21.8351 7.66732 21.8351H6.66723H5.33795C5.27545 21.8351 5.21294 21.831 5.15044 21.8268C5.10043 21.831 5.05043 21.8351 5.00043 21.8351H4.3337C3.41279 21.8351 2.66689 21.0893 2.66689 20.1683V15.5013C2.66689 15.4638 2.66689 15.4221 2.67106 15.3846V12.4844H1.33345C0.583383 12.4844 0 11.901 0 11.1467C0 10.7717 0.125011 10.4383 0.416702 10.1467L11.1009 0.833362C11.3926 0.54167 11.726 0.5 12.0177 0.5C12.3094 0.5 12.6427 0.58334 12.8928 0.791691L23.5353 10.1467C23.8687 10.4383 24.0354 10.7717 23.9937 11.1467Z"/>
</svg>`,
  calendar: `<svg xmlns="http://www.w3.org/2000/svg" width="21" height="24" viewBox="0 0 21 24">
    <path d="M6 0C6.82969 0 7.5 0.670312 7.5 1.5V3H13.5V1.5C13.5 0.670312 14.1703 0 15 0C15.8297 0 16.5 0.670312 16.5 1.5V3H18.75C19.9922 3 21 4.00781 21 5.25V7.5H0V5.25C0 4.00781 1.00781 3 2.25 3H4.5V1.5C4.5 0.670312 5.17031 0 6 0ZM0 9H21V21.75C21 22.9922 19.9922 24 18.75 24H2.25C1.00781 24 0 22.9922 0 21.75V9ZM3.75 12C3.3375 12 3 12.3375 3 12.75V17.25C3 17.6625 3.3375 18 3.75 18H8.25C8.6625 18 9 17.6625 9 17.25V12.75C9 12.3375 8.6625 12 8.25 12H3.75Z"/>
</svg>`,
  cart: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
    <path d="M8.57143 2.57143C8.57143 1.15179 9.72321 0 11.1429 0H12.8571C14.2768 0 15.4286 1.15179 15.4286 2.57143V21.4286C15.4286 22.8482 14.2768 24 12.8571 24H11.1429C9.72321 24 8.57143 22.8482 8.57143 21.4286V2.57143ZM0 12.8571C0 11.4375 1.15179 10.2857 2.57143 10.2857H4.28571C5.70536 10.2857 6.85714 11.4375 6.85714 12.8571V21.4286C6.85714 22.8482 5.70536 24 4.28571 24H2.57143C1.15179 24 0 22.8482 0 21.4286V12.8571ZM19.7143 3.42857H21.4286C22.8482 3.42857 24 4.58036 24 6V21.4286C24 22.8482 22.8482 24 21.4286 24H19.7143C18.2946 24 17.1429 22.8482 17.1429 21.4286V6C17.1429 4.58036 18.2946 3.42857 19.7143 3.42857Z"/>
</svg>`,
  more: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="7" viewBox="0 0 24 7">
    <path d="M0 3.11111C0 2.28599 0.327777 1.49467 0.911223 0.911224C1.49467 0.327777 2.28599 0 3.11111 0C3.93623 0 4.72755 0.327777 5.311 0.911224C5.89445 1.49467 6.22222 2.28599 6.22222 3.11111C6.22222 3.93623 5.89445 4.72755 5.311 5.311C4.72755 5.89445 3.93623 6.22222 3.11111 6.22222C2.28599 6.22222 1.49467 5.89445 0.911223 5.311C0.327777 4.72755 0 3.93623 0 3.11111ZM8.88889 3.11111C8.88889 2.28599 9.21667 1.49467 9.80011 0.911224C10.3836 0.327777 11.1749 0 12 0C12.8251 0 13.6164 0.327777 14.1999 0.911224C14.7833 1.49467 15.1111 2.28599 15.1111 3.11111C15.1111 3.93623 14.7833 4.72755 14.1999 5.311C13.6164 5.89445 12.8251 6.22222 12 6.22222C11.1749 6.22222 10.3836 5.89445 9.80011 5.311C9.21667 4.72755 8.88889 3.93623 8.88889 3.11111ZM20.8889 0C21.714 0 22.5053 0.327777 23.0888 0.911224C23.6722 1.49467 24 2.28599 24 3.11111C24 3.93623 23.6722 4.72755 23.0888 5.311C22.5053 5.89445 21.714 6.22222 20.8889 6.22222C20.0638 6.22222 19.2724 5.89445 18.689 5.311C18.1056 4.72755 17.7778 3.93623 17.7778 3.11111C17.7778 2.28599 18.1056 1.49467 18.689 0.911224C19.2724 0.327777 20.0638 0 20.8889 0Z"/>
</svg>`,
  plus: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
    <path d="M11.5385 1.53846C11.5385 0.6875 10.851 0 10 0C9.14904 0 8.46154 0.6875 8.46154 1.53846V8.46154H1.53846C0.6875 8.46154 0 9.14904 0 10C0 10.851 0.6875 11.5385 1.53846 11.5385H8.46154V18.4615C8.46154 19.3125 9.14904 20 10 20C10.851 20 11.5385 19.3125 11.5385 18.4615V11.5385H18.4615C19.3125 11.5385 20 10.851 20 10C20 9.14904 19.3125 8.46154 18.4615 8.46154H11.5385V1.53846Z"/>
</svg>`,
};

 

(이전에는 피그마 개발자 도구 무료라서 바로 복붙이 가능했는데 이제 불가능해져서 슬프네요.)

 

navigation/BottomTabsNavigator.tsx

// react, react-native
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {SvgXml} from 'react-native-svg';

// assets, utils
import {svg} from '../assets/svg';

// components
import Home from '../screens/Home';
import Calendar from '../screens/Calendar';
import Chart from '../screens/Chart';
import More from '../screens/More';

const BottomTabsNavigator = () => {
  const Tab = createBottomTabNavigator();

  return (
    <Tab.Navigator initialRouteName="Home">
      <Tab.Screen
        name="Home"
        component={Home}
        options={{
          title: '홈',
          tabBarIcon: ({color}) => <SvgXml xml={svg.home} fill={color} />,
        }}
      />
      <Tab.Screen name="Calendar" component={Calendar} />
      <Tab.Screen name="Chart" component={Chart} />
      <Tab.Screen name="More" component={More} />
    </Tab.Navigator>
  );
};

export default BottomTabsNavigator;

 

 

 

세팅을 했는데 변화가 아무것도 없어서 터미널에 아래와 같이 코드를 써주었습니다.

(npm run ~을 다시 해주면 될 것 같습니다.)

cd ios && pod install

이렇게 했더니 ios는 해결되었는데 android는 다시시작하니 잘 작동되었습니다.

 

다시 실행

// android 실행
npm run android

// ios 실행
npm run ios

 

이제 디자인 화면과 똑같이 커스텀 해보겠습니다.

 

react-navigation 커스텀


navigation/BottomTabsNavigator.tsx : 하단 내비게이션 커스텀

// react, react-native
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {SvgXml} from 'react-native-svg';

// assets, utils
import {svg} from '../assets/svg';

// components
import Home from '../screens/Home';
import Calendar from '../screens/Calendar';
import Chart from '../screens/Chart';
import More from '../screens/More';

const BottomTabsNavigator = () => {
  const Tab = createBottomTabNavigator();

  return (
    <Tab.Navigator
      initialRouteName="Home"
      screenOptions={{
        headerShown: false,
        tabBarStyle: {
          height: 48,
          borderTopColor: '#D9D9D9',
          elevation: 0,
        },
        tabBarActiveTintColor: '#FFA800',
        tabBarInactiveTintColor: '#D9D9D9',
        tabBarShowLabel: false,
      }}>
      <Tab.Screen
        name="Home"
        component={Home}
        options={{
          title: '홈',
          tabBarIcon: ({color}) => <SvgXml xml={svg.home} fill={color} />,
        }}
      />
      <Tab.Screen
        name="Calendar"
        component={Calendar}
        options={{
          title: '달력',
          tabBarIcon: ({color}) => <SvgXml xml={svg.calendar} fill={color} />,
        }}
      />
      <Tab.Screen
        name="Chart"
        component={Chart}
        options={{
          title: '그래프',
          tabBarIcon: ({color}) => <SvgXml xml={svg.cart} fill={color} />,
        }}
      />
      <Tab.Screen
        name="More"
        component={More}
        options={{
          title: '더보기',
          tabBarIcon: ({color}) => <SvgXml xml={svg.more} fill={color} />,
        }}
      />
    </Tab.Navigator>
  );
};

export default BottomTabsNavigator;

 

navigation/StackNavigator.tsx : 스택 네비게이션 커스텀

헤더 부분을 false로 바꾸어주었습니다.

// react, react-native
import {createNativeStackNavigator} from '@react-navigation/native-stack';

// components
import BottomTabsNavigator from './BottomTabsNavigator';
import Record from '../screens/Record';

const StackNavigator = () => {
  const Stack = createNativeStackNavigator();

  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Main"
        component={BottomTabsNavigator}
        options={{headerShown: false}}
      />
      <Stack.Screen
        name="Record"
        component={Record}
        options={{headerShown: false}}
      />
    </Stack.Navigator>
  );
};

export default StackNavigator;

 

App.tsx : 내비게이션 커스텀

배경이 회색이라 흰색으로 바꿔주었습니다.

// react, react-native
import {NavigationContainer} from '@react-navigation/native';
import StackNavigator from './navigation/StackNavigator';

const App = () => {
  return (
    <NavigationContainer theme={ colors: { background: "white" } }}>
      <StackNavigator />
    </NavigationContainer>
  );
};

export default App;

이렇게만 작성해주고 싶지만 이러면 colors에 타입에러가 뜹니다.

 

해결방안

React Navigation의 NavigationContainer에서 사용하는 테마는 기본적으로 DefaultTheme과 호환되는 객체여야 합니다.

따라서 colors 객체의 타입을 정확히 설정해야 합니다.

https://velog.io/@mementomori/NavigationContainer-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%A0%84%EC%97%AD-theme-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95-React-Native

 

NavigationContainer 이용해서 전역 theme 사용방법 - React Native

https://reactnavigation.org/docs/themes/theme 객체 생성(ex> "MyTheme")theme 객체 내의 속성에 해당하는 값 입력: colors의 경우, primary,background,card,text,border,noti

velog.io

App.tsx

// react, react-native
import {NavigationContainer, DefaultTheme} from '@react-navigation/native';
import StackNavigator from './navigation/StackNavigator';

const App = () => {
  const customTheme = {
    ...DefaultTheme,
    colors: {
      ...DefaultTheme.colors,
      background: '#fff', // 흰색 배경색
    },
  };

  return (
    <NavigationContainer theme={customTheme}>
      <StackNavigator />
    </NavigationContainer>
  );
};

export default App;

728x90
반응형
Comments