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)
이 두개를 사용했는데 사용하기 전에 먼저
- https://reactnavigation.org/docs/getting-started (아래 설치의 링크)
- npm install @react-navigation/native --save(package.json안에 저장하는 것)
- npx expo install react-native-screens react-native-safe-area-context
위에 것을 순서대로 설치 후 아래 내용을 import 한다.
import { NavigationContainer } from "@react-navigation/native";
- https://reactnavigation.org/docs/navigation-container
- <NavigationContainer> </NavigationContainer>로 전체를 감싸주고 시작한다.
그 후
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;
`;