absoluteFill
absoluteFill
하나만 써도 됨<SwiperChildView>
<BackgroundImg
style={StyleSheet.absoluteFill}
source={require('../assets/banner.png')}
/>
<LinearGradient
style={StyleSheet.absoluteFill}
colors={['transparent', 'black']}
/>
</SwiperChildView>
import * as React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
export default function App() {
return (
<View style={styles.container}><LinearGradient
// Background Linear Gradient
colors={['rgba(0,0,0,0.8)', 'transparent']}
style={styles.background}
/>
<LinearGradient
// Button Linear Gradient
colors={['#4c669f', '#3b5998', '#192f6a']}
style={styles.button}>
<Text style={styles.text}>Sign in with Facebook</Text></LinearGradient></View>);
}
설치 npm i react-native-swiper --save
swiper import import Swiper from 'react-native-swiper'
그냥 Swiper컴포넌트 안에 View컴포넌트 넣고 하면 됨
flex: 1; 해줘야함
Movies.js
export default class SwiperComponent extends Component {
render() {
return (
<Swiper style={styles.wrapper} showsButtons={true}>
<View style={styles.slide1}>
<Text style={styles.text}>Hello Swiper</Text>
</View>
<View style={styles.slide2}>
<Text style={styles.text}>Beautiful</Text>
</View>
<View style={styles.slide3}>
<Text style={styles.text}>And simple</Text>
</View>
</Swiper>
)
}
}
const styles = StyleSheet.create({ ... });
SwiperChildView
// 스와이퍼 3분의 1높이만큼 표시한다
const SwiperChildView = styled.View`
flex: 1;
justify-content: flex-end;
height: ${SCREEN_HEIGHT / 3 + 'px'};
background-color: green;
`;
Dimensions
기기의 실제 너비와 높이 구하기
import { Dimensions } from 'react-native';
// 구조분해할당을 통해 WIDTH와 HEIGHT 뽑아내기
export const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } =
Dimensions.get('window');
페이징 인디케이터 가리기
<*Swiper* *height*='100%' *showsPagination*={false}>
손으로 스와이퍼를 넘기지 않아도 일정시간이 되면 자동으로 넘길 수 있게 해줌
autoplay
마지막 페이지에서 맨 앞페이지로 스와이프할 수 있게 해주는 속성
loop
<Swiper height='100%' showsPagination={false} autoplay loop>
// Movies.js
import React from 'react';
import { ScrollView, StyleSheet } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import Swiper from 'react-native-swiper';
export default function Movies({ navigation: { navigate } }) {
const title = '영화제목';
const rating = 7.5;
const overview = '재밌어요';
return (
<ScrollView>
<Swiper height='100%' showsPagination={false} autoplay loop>
<SwiperChildView>
<Text style={styles.text}>Hello Swiper</Text>
<BackgroundImg
style={StyleSheet.absoluteFill}
source={require('../assets/image.jpg')}
/>
<LinearGradient
// Background Linear Gradient
style={StyleSheet.absoluteFill}
colors={['transparent', 'black']}
/>
<Row>
<Poster source={require('../assets/image.jpg')} />
<Column>
<Title>{title}</Title>
<Rating>⭐{rating}</Rating>
<Overview>
{overview.slice(0, 150)}
{overview.length > 150 && '...'}
</Overview>
</Column>
</Row>
</SwiperChildView>
</Swiper>
<ListTitle>Top Rated Movies</ListTitle>
<ScrollView></ScrollView>
<ListTitle>Upcoming Movies</ListTitle>
<UpcomingRow onPress={() => {}}></UpcomingRow>
<UpcomingRow onPress={() => {}}></UpcomingRow>
</ScrollView>
);
}
const Rating = styled.View`
color: white;
margin-top: 5px;
margin-bottom: 5px;
`;
const SwiperChildView = styled.View`
flex: 1;
justify-content: flex-end;
height: ${SCREEN_HEIGHT / 3 + 'px'};
background-color: green;
`;
const BackgroundImg = styled.Image`
height: 100%;
width: 100%;
`;
// 기본값은 true
const [isLoading, setIsLoading] = useState(true);
// 로딩중이라면 Loader안의 ActivityIndicator가 보이고
// 로딩중이 아니라면 return값이 나온다.
if (isLoading) {
return (
<Loader>
<ActivityIndicator />
</Loader>
);
}
return (
<FlatList
onEndReached={fetchMore}
onEndReachedThreshold={0.5}
refreshing={isRefreshing}
onRefresh={onRefresh}
ListHeaderComponent={
<>
const getNowPlayings = async () => {
const {results} = await fetch(
`${BASE_URL}/now_playing?api_key=${API_KEY}&language=en=US&page=1`
).then((res) => res.json());
setNowPlayings(results);
// setIsLoading이 false가 되어야 함
setIsLoading(false)
};
useEffect(() => {
getNowPlayings();
}, [])
if (isLoading) {
return (
<Loader>
<ActivityIndicator />
</Loader>
);
}
return (
<FlatList
onEndReached={fetchMore}
onEndReachedThreshold={0.5}
refreshing={isRefreshing}
onRefresh={onRefresh}
ListHeaderComponent={
<>
const Loader = styled.View`
flex: 1;
justify-content: center;
align-items: center;
`;
<Swiper height='100%' showsPagination={false} autoplay loop>
// nowPlayingData라는 배열을 가지고 map으로 뿌릴 것
// 배열 하나의 요소는 영화 객체 movie인데 이 movie객체를 갖고 map을 뿌릴 것
{nowPlayingData.results.map((movie) => (
<Slide key={movie.id} movie={movie} />
))}
</Swiper>
<Swiper height='100%' showsPagination={false} autoplay loop>
{nowPlayingData.results.map((movie) => (
// 인터넷 상에 있는 이미지를 가져올 땐 객체{}안에 uri넣어주기
<BackgroundImg
source={{uri: `https://image.tmdb.org/t/p/w500${movie.backdrop_path}}}
/>
// util.js
// path를 매개변수로 받아서 return하기
// 전체 url을 문자열로 리턴해주는 함수
export const getImgPath = (path) => {
return `https://image.tmdb.org/t/p/w500${path}`;
};
// Movie.js
// 위의 uri를 이걸로 바꾸기
<Poster
source={{uri: getImgPath(movie.poster_path)}}
/>
// Slide.js컴포넌트 만들기
// Movie.js에서 복붙해서 컴포넌트로 따로 빼기
// 컴포넌트가 길다보니 불러와야하는 게 많음
import React from "react";
import { StyleSheet } from "react-native";
import { getImgPath, SCREEN_HEIGHT } from "../util";
import styled from "@emotion/native";
import { LinearGradient } from "expo-linear-gradient";
import { useNavigation } from "@react-navigation/native";
export default function Slide({ movie }) {
const { navigate } = useNavigation();
return (
<SwiperChildView>
<BackgroundImg
style={StyleSheet.absoluteFill}
// style={{ position: "absolute", top: 0, left: 0 }}
source={{
uri: getImgPath(movie.backdrop_path),
}}
/>
<LinearGradient
style={StyleSheet.absoluteFill}
colors={["transparent", "black"]}
/>
<Row
onPress={() =>
navigate("Stacks", {
screen: "Detail",
params: { movieId: movie.id },
})
}
>
<Poster
source={{
uri: getImgPath(movie.poster_path || ""),
}}
/>
<Column>
<Title>{movie.title}</Title>
<Rating>⭐️{movie.vote_average}/10</Rating>
<Overview>
{movie.overview.slice(0, 150)}
{movie.overview.length > 150 && "..."}
</Overview>
</Column>
</Row>
</SwiperChildView>
);
}
const SwiperChildView = styled.TouchableOpacity`
flex: 1;
justify-content: flex-end;
height: ${SCREEN_HEIGHT / 3 + "px"};
background-color: green;
`;
const BackgroundImg = styled.Image`
height: 100%;
width: 100%;
`;
const Row = styled.TouchableOpacity`
flex: 1;
flex-direction: row;
align-items: flex-end;
`;
const Column = styled.View`
width: 65%;
margin-left: 10px;
margin-bottom: 10px;
`;
const Poster = styled.Image`
width: 100px;
height: 160px;
/* height: 100%; */
margin-left: 10px;
margin-bottom: 10px;
`;
const Title = styled.Text`
font-size: 20px;
font-weight: 600;
color: white;
`;
const Overview = styled.Text`
font-size: 12px;
color: white;
`;
const Rating = styled.Text`
color: white;
margin-top: 5px;
margin-bottom: 5px;
`;
<Swiper height='100%' showsPagination={false} autoplay loop>
{nowPlayingData.results.map((movie) => (
// 맵을 미리 뿌렸으니까 키값넣기
// 키값은 movie.id
<Slide key={movie.id} movie={movie} />
))}
</Swiper>
export default function Slide({ movie }) {
const { navigate } = useNavigation();
return (
<SwiperChildView>
<BackgroundImg
style={StyleSheet.absoluteFill}
// style={{ position: "absolute", top: 0, left: 0 }}
source={{
uri: getImgPath(movie.backdrop_path),
}}
/>
<LinearGradient
style={StyleSheet.absoluteFill}
colors={["transparent", "black"]}
/>
<Row
onPress={() =>
navigate("Stacks", {
screen: "Detail",
params: { movieId: movie.id },
})
}
>
<Poster
source={{
uri: getImgPath(movie.poster_path || ""),
}}
/>
<Column>
<Title>{movie.title}</Title>
<Rating>⭐️{movie.vote_average}/10</Rating>
<Overview>
{movie.overview.slice(0, 150)}
{movie.overview.length > 150 && "..."}
</Overview>
</Column>
</Row>
</SwiperChildView>
);
}