카테고리 없음

Til(2023.01.04)

prdg 2023. 1. 5. 09:55

react native앱 영화 UI그리기 (+ react native 네비게이터 제작)

 

네비게이터는 navigation이란 폴더를 만들어 root.jsx안에 bottom Taps navigater와 native Stack Navigater를 합쳤다.

https://reactnavigation.org/docs/native-stack-navigator (NativeStack)

https://reactnavigation.org/docs/bottom-tab-navigator (Bottom Tabs)

이 두개를 사용했는데 사용하기 전에 먼저

 

위에 것을 순서대로 설치 후 아래 내용을 import 한다.

import { NavigationContainer } from "@react-navigation/native";

 

그 후

https://reactnavigation.org/docs/native-stack-navigator (npm install @react-navigation/native-stack --save)

https://reactnavigation.org/docs/bottom-tab-navigator (npm install @react-navigation/bottom-tabs --save)

사용할 네비게이터를 install 해준다.

각 사용할 component에 

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

const Stack = createNativeStackNavigator();
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

그리고 각 링크 안에 사용방법처럼 사용하면 된다.

 

UI는 @emotion/native을 사용해 제작했다.

component안에 Movie.jsx, My.jsx 만들어서 사용했고

component안에서 전체를 ScrollView로 감싼 후 시작했다.

검은 배경은 App.jsx에 DarkTheme을 import한 후 theme의 형태로 NavigationContainer에 넣어줬다.

import { DarkTheme } from "@react-navigation/native";

export default function App() {
  return (
    <NavigationContainer theme={DarkTheme}>
      <Root />
    </NavigationContainer>
  );
}

이미지는 이런 식으로 사용 후 @emotion/native로 image속성을 줬고

        <MovieImage source={require("./../assets/movie.jpg")} />

일정 길이 이상되면 붙는...은 width 속성을 주고 

numberOfLinew (뒤 숫자대로 줄을 정한다.)

ellipsizeMode (뒤 속성대로 ...을 뒤에 붙일지 중간에 붙일지 그냥 자를지 등을 설정한다.)

          <TopText numberOfLines={1} ellipsizeMode="tail">
            Top Gun : Maverick
          </TopText>

중간 가로 스크롤은 ScrollView에 horizontal을 true로 설정해서 사용했다.

      <ScrollView horizontal={true}> </ScrollView>

각 박스들은 클릭효과(onPress)를 위해 TouchableOpacity로 감싸줬다.

Movie.jsx전체 코드

import React from "react";
import {
  Text,
  View,
  TouchableOpacity,
  Image,
  ScrollView,
  SafeAreaView,
} from "react-native";
import styled, { css } from "@emotion/native";

export default function Movie() {
  return (
    <ScrollView>
      {/* 메인비주얼 */}
      <MainVisual>
        <MovieImage source={require("./../assets/movie.jpg")} />
        <MainVisualContent>
          <MainVisualImage source={require("./../assets/movie.jpg")} />
          <View>
            <MainTitle>Top Gun : Maverick</MainTitle>
            <MainStar>⭐️ 8.3 / 10</MainStar>
            <MainText>
              texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext
            </MainText>
          </View>
        </MainVisualContent>
      </MainVisual>

      {/* Top Rated Movie */}
      <TopTitle>Top Rated Movies</TopTitle>
      <ScrollView horizontal={true}>
        <TopViewBox>
          <TopImage source={require("./../assets/movie.jpg")} />
          <TopStar>⭐️ 8.3 / 10</TopStar>
          <TopText numberOfLines={1} ellipsizeMode="tail">
            Top Gun : Maverick
          </TopText>
        </TopViewBox>

        <TopViewBox>
          <TopImage source={require("./../assets/movie.jpg")} />
          <TopStar>⭐️ 8.3 / 10</TopStar>
          <TopText numberOfLines={1} ellipsizeMode="tail">
            Top Gun : Maverick
          </TopText>
        </TopViewBox>

        <TopViewBox>
          <TopImage source={require("./../assets/movie.jpg")} />
          <TopStar>⭐️ 8.3 / 10</TopStar>
          <TopText numberOfLines={1} ellipsizeMode="tail">
            Top Gun : Maverick
          </TopText>
        </TopViewBox>

        <TopViewBox>
          <TopImage source={require("./../assets/movie.jpg")} />
          <TopStar>⭐️ 8.3 / 10</TopStar>
          <TopText numberOfLines={1} ellipsizeMode="tail">
            Top Gun : Maverick
          </TopText>
        </TopViewBox>
      </ScrollView>

      {/* Upcoming Movies */}
      <TopTitle>Upcoming Movies</TopTitle>

      <Upcoming>
        <UpcomingImage source={require("./../assets/movie.jpg")} />
        <View>
          <UpcomingTitle>Top Gun : Maverick</UpcomingTitle>
          <UpcomingDate>2023-1-1</UpcomingDate>
          <UpcomingText numberOfLines={3} ellipsizeMode="tail">
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
          </UpcomingText>
        </View>
      </Upcoming>

      <Upcoming>
        <UpcomingImage source={require("./../assets/movie.jpg")} />
        <View>
          <UpcomingTitle>Top Gun : Maverick</UpcomingTitle>
          <UpcomingDate>2023-1-1</UpcomingDate>
          <UpcomingText numberOfLines={3} ellipsizeMode="tail">
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
          </UpcomingText>
        </View>
      </Upcoming>

      <Upcoming>
        <UpcomingImage source={require("./../assets/movie.jpg")} />
        <View>
          <UpcomingTitle>Top Gun : Maverick</UpcomingTitle>
          <UpcomingDate>2023-1-1</UpcomingDate>
          <UpcomingText numberOfLines={3} ellipsizeMode="tail">
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
          </UpcomingText>
        </View>
      </Upcoming>

      <Upcoming>
        <UpcomingImage source={require("./../assets/movie.jpg")} />
        <View>
          <UpcomingTitle>Top Gun : Maverick</UpcomingTitle>
          <UpcomingDate>2023-1-1</UpcomingDate>
          <UpcomingText numberOfLines={3} ellipsizeMode="tail">
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
            texttexttexttexttexttexttexttexttexttexttexttexttext
          </UpcomingText>
        </View>
      </Upcoming>
    </ScrollView>
  );
}

/*****************/
/*****************/
/*****************/
const MainVisual = styled.View`
  height: 300px;
`;
const MovieImage = styled.Image`
  width: 100%;
  height: 300px;
  position: absolute;
  bottom: 0;
  opacity: 0.5;
`;
const MainVisualContent = styled.View`
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  position: absolute;
  bottom: 10px;
  left: 20px;
`;

const MainVisualImage = styled.Image`
  width: 100px;
  height: 150px;
`;
const MainTitle = styled.Text`
  font-size: 20px;
  font-weight: 600;
  color: #fff;
  margin-left: 15px;
`;
const MainStar = styled.Text`
  color: #ccc;
  font-weight: 500;
  margin: 5px 0 5px 15px;
`;
const MainText = styled.Text`
  color: #ccc;
  font-weight: 500;
  width: 200px;
  margin-left: 15px;
`;

/*****************/
/*****************/
/*****************/
const TopTitle = styled.Text`
  //Upcoming까지
  font-size: 20px;
  color: yellow;
  margin-top: 30px;
  margin-bottom: 10px;
  margin-left: 10px;
`;
const TopViewBox = styled.TouchableOpacity`
  width: 130px;
  height: 250px;
  background-color: #727272;
  border-radius: 5px;
  overflow: hidden;
  margin-left: 10px;
  margin-right: 5px;
`;
const TopImage = styled.Image`
  width: 130px;
  height: 180px;
`;
const TopStar = styled.Text`
  color: #ccc;
  margin: 20px 0 5px 10px;
`;
const TopText = styled.Text`
  color: #fff;
  width: 100px;
  margin-left: 10px;
`;

/*****************/
/*****************/
/*****************/
const Upcoming = styled.TouchableOpacity`
  width: 100%;
  height: 170px;
  display: flex;
  flex-direction: row;
  align-items: center;
`;
const UpcomingImage = styled.Image`
  width: 100px;
  height: 150px;
  border-radius: 5px;
  margin-left: 10px;
`;
const UpcomingTitle = styled.Text`
  color: #fff;
  font-size: 18px;
  margin-left: 10px;
`;
const UpcomingDate = styled.Text`
  color: #ccc;
  margin: 10px;
`;
const UpcomingText = styled.Text`
  width: 250px;
  color: #ccc;
  margin-left: 10px;
`;