- 2주차에 만들었던 AboutPage 를 MainPage 에 연결시키고, AboutPage 에는 인스타나 블로그 주소 혹은 아무 주소를 하단 버튼에 연결시켜주자.
- 꿀팁 찜 페이지(LikePage) 화면을 만들어주자.
- 아직은 기존의 데이터와 연결시키는 것이 아니라, 기본 데이터를 가지고 화면을 그려보자.
가이드
- 메인에 TouchableOpacity 버튼을 두고 navigate 를 연결시켜서 이동시켜주자
- Stack.Screen 에 AboutPage.js 를 연결시켜야 한다.
- AboutPage 상단바는 흰색이다.
- 메인 페이지에 위치해있던 꿀팁 찜 카테고리에 꿀팁 찜 페이지를 연결시켜주자.
- 찜 목록에 있는 카드도 컴포넌트(LikeCard)로 분리해서 만들자. → 찜 삭제 버튼 추가
- LikeCard 에서는 TouchableOpacity 로 감싸는 것이 아닌, View 태그로 카드 전체를 감싸주도록 바꿔준다.
소개 페이지 연결
StackNavigator.js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';
import AboutPage from '../pages/AboutPage';
const Stack = createStackNavigator();
const StackNavigator = () =>{
return (
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "white",
borderBottomColor: "white",
shadowColor: "white",
height:100
},
headerTitleAlign:'left',
headerTintColor: "#000",
headerBackTitleVisible: false
}}
>
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
{/* AboutPage 추가 */}
<Stack.Screen name="AboutPage" component={AboutPage}/>
</Stack.Navigator>
)
}
export default StackNavigator;
AboutPage.js
import React,{useEffect} from 'react'
import {View,Text,StyleSheet,Image, TouchableOpacity} from 'react-native'
import { StatusBar } from 'expo-status-bar';
export default function AboutPage({navigation,route}){
const aboutImage = "https://storage.googleapis.com/sparta-image.appspot.com/lecture/about.png"
useEffect(()=>{
navigation.setOptions({
title:"소개 페이지",
headerStyle: {
backgroundColor: '#1F266A',
shadowColor: "#1F266A",
},
headerTintColor: "#fff",
})
},[])
return (
<View style={styles.container}>
<StatusBar style="light" />
<Text style={styles.title}>HI! 스파르타코딩 앱개발 반에 오신것을 환영합니다</Text>
<View style={styles.textContainer}>
<Image style={styles.aboutImage} source={{uri:aboutImage}} resizeMode={"cover"}/>
<Text style={styles.desc01}>많은 내용을 간결하게 담아내려 노력했습니다!</Text>
<Text style={styles.desc02}>꼭 완주 하셔서 꼭 여러분것으로 만들어가시길 바랍니다</Text>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>여러분의 인스타계정</Text>
</TouchableOpacity>
</View>
</View>)
}
const styles = StyleSheet.create({
container: {
flex:1,
backgroundColor:"#1F266A",
alignItems:"center"
},
title: {
fontSize:30,
fontWeight:"700",
color:"#fff",
paddingLeft:30,
paddingTop:20,
paddingRight:30
},
textContainer: {
width:300,
height:500,
backgroundColor:"#fff",
marginTop:50,
borderRadius:30,
justifyContent:"center",
alignItems:"center"
},
aboutImage:{
width:150,
height:150,
borderRadius:30
},
desc01: {
textAlign:"center",
fontSize:20,
fontWeight:"700",
paddingLeft:22,
paddingRight:22
},
desc02: {
textAlign:"center",
fontSize:15,
fontWeight:"700",
padding:22
},
button:{
backgroundColor:"orange",
padding:20,
borderRadius:15
},
buttonText: {
color:"#fff",
fontSize:15,
fontWeight:"700"
}
})
MainPage.js
import React, {useState, useEffect} from "react";
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
ScrollView,
SafeAreaView,
} from "react-native";
import { StatusBar } from "expo-status-bar";
import data from "../data.json";
import Card from "../components/Card";
import Loading from "../components/Loading";
const mainImg =
"https://storage.googleapis.com/sparta-image.appspot.com/lecture/main.png";
const cardImg =
"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3";
// 페이지 이동을 구현
// Stack.Screen 으로부터 MainPage 는 navigation과 route 를 인자로 전달받는다.
export default function MainPage({navigation, route}) {
const [state, setState] = useState([]);
const [ready, setReady] = useState(true);
const [cateState, setCateState] = useState([]);
useEffect(() => {
setTimeout(()=>{
// 헤더의 타이틀 변경
navigation.setOptions({
title: '나만의 꿀팁'
})
setState(data.tip)
setCateState(data.tip)
setReady(false)
}, 1000)
}, [])
const category = (cate) => {
if (cate == '전체보기') {
setCateState(state)
} else {
setCateState(state.filter((d) => {
return d.category == cate
}))
}
}
// 날씨
let todayWeather = 10 + 17;
let todayCondition = '흐림';
return ready ? <Loading /> : (
<SafeAreaView>
<ScrollView style={styles.container}>
<StatusBar style="black" />
{/* 타이틀 */}
{/* <Text style={styles.title}>나만의 꿀팁</Text> */}
<Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition}</Text>
<TouchableOpacity></TouchableOpacity>
{/* 메인 이미지 */}
<Image source={{ uri: mainImg }} style={styles.mainImage} />
{/* 탭 버튼 목록 */}
<ScrollView
horizontal
style={styles.btnContainer}
indicatorStyle={"white"}
>
<TouchableOpacity style={styles.btnAll} onPress={()=>{category('전체보기')}}>
<Text style={styles.textStyle}>전체보기</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn01} onPress={()=>{category('생활')}}>
<Text style={styles.textStyle}>생활</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn02} onPress={()=>{category('재테크')}}>
<Text style={styles.textStyle}>재테크</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn03} onPress={()=>{category('반려견')}}>
<Text style={styles.textStyle}>반려견</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn04} onPress={()=>{category('꿀팁 찜')}}>
<Text style={styles.textStyle}>꿀팁 찜</Text>
</TouchableOpacity>
</ScrollView>
{/* 카드 목록 */}
{/* 카드 컴포넌트 눌렀을 때 페이지가 이동될 수 있도록 navigation 을 넘겨준다.*/}
{cateState.map((content, i) => {
return <Card content={content} key={i} navigation={navigation} />;
})}
</ScrollView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
},
title: {
fontSize: 25,
marginTop: 20,
marginLeft: 20,
fontWeight: "bold",
},
weather: {
alignSelf: 'flex-end',
paddingRight: 20,
},
mainImage: {
width: "90%",
height: 200,
borderRadius: 5,
alignSelf: "center",
margin: 10,
},
btnContainer: {
margin: 20,
height: 60,
},
btnAll: {
backgroundColor: "#20b2aa",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn01: {
backgroundColor: "rgb(246, 204, 113)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn02: {
backgroundColor: "rgb(241, 156, 131)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn03: {
backgroundColor: "rgb(178, 223, 208)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn04: {
backgroundColor: "rgb(238, 150, 180)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
textStyle: {
color: "#fff",
},
});
꿀팁 찜 페이지 구현
LikeCard.js
import React from 'react';
import {View, Image, Text, StyleSheet,TouchableOpacity} from 'react-native'
//MainPage로 부터 navigation 속성을 전달받아 Card 컴포넌트 안에서 사용
export default function LikeCard({content,navigation}){
return(
//카드 자체가 버튼역할로써 누르게되면 상세페이지로 넘어가게끔 TouchableOpacity를 사용
<View style={styles.card}>
<Image style={styles.cardImage} source={{uri:content.image}}/>
<View style={styles.cardText}>
<Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
<Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
<Text style={styles.cardDate}>{content.date}</Text>
</View>
</View>
)
}
const styles = StyleSheet.create({
card:{
flex:1,
flexDirection:"row",
margin:10,
borderBottomWidth:0.5,
borderBottomColor:"#eee",
paddingBottom:10
},
cardImage: {
flex:1,
width:100,
height:100,
borderRadius:10,
},
cardText: {
flex:2,
flexDirection:"column",
marginLeft:10,
},
cardTitle: {
fontSize:20,
fontWeight:"700"
},
cardDesc: {
fontSize:15
},
cardDate: {
fontSize:10,
color:"#A6A6A6",
}
});
LikePage.js
import React,{useState, useEffect} from 'react';
import {ScrollView, Text, StyleSheet} from 'react-native';
import LikeCard from '../components/LikeCard';
import Card from '../components/Card';
export default function LikePage({navigation,route}){
const [tip, setTip] = useState([{
"idx":3,
"category":"재테크",
"title":"잠자는 내 돈을 찾아라",
"image": "https://storage.googleapis.com/sparta-image.appspot.com/lecture/money1.png",
"desc":"‘새는 돈’에는 미처 몰랐던 카드 포인트, 휴면예금이나 환급금도 포함됩니다. 확실히 파악하지 못한 잠자는 돈을 찾아보고 자투리 돈들을 모으는 것도 중요합니다. 케이블방송, 위성방송 서비스를 이용하면서 중복 납부한 요금, 셋톱박스 보증금 등 돌려받지 않은 돈이 있는지 확인 해보세요. 또, 카드 포인트 통합 조회 서비스를 이용해 여러 개의 카드 포인트가 모두 얼마인지 체크해두는 것이 좋습니다. 보험해약 환급금, 휴면 보험금이나 휴면 예금을 찾아보고 돌려받는 일도 요즘에는 어렵지 않습니다.",
"date":"2020.09.09"
},
{
"idx":4,
"category":"재테크",
"title":"할인행사, 한정할인판매 문구의 함정 탈출!",
"image": "https://storage.googleapis.com/sparta-image.appspot.com/lecture/money2.png",
"desc":"‘안 사면 100% 할인’이라는 말 들어보셨나요? 견물생심, 좋은 물건을 보면 사고 싶기 마련입니다. 특히 대대적인 ‘할인 행사’ 중인 대형 마트에 갔을 때는 말할 것도 없겠죠. 따라서 생필품을 살 때, 한꺼번에 사서 사용하는 것보다 필요할 때 조금씩 구매하는 편이 좋습니다. 장을 보면서 대형마트에 자주 가다 보면 지금 필요한 것뿐 아니라 앞으로 필요할 것까지 사게 되어 지출이 커지기 때문입니다. 특히 할인 품목을 보면 뜻하지 않은 소비를 하는 경우도 많아진다. 홈쇼핑, 대형마트 등의 ‘할인행사’, ‘한정할인판매’ 등의 문구를 조심하세요. ",
"date":"2020.09.09"
}])
useEffect(()=>{
navigation.setOptions({
title:'꿀팁 찜'
})
})
return (
<ScrollView style={styles.container}>
{
tip.map((content,i)=>{
return(<LikeCard key={i} content={content} navigation={navigation}/>)
})
}
</ScrollView>
)
}
const styles = StyleSheet.create({
container:{
backgroundColor:"#fff"
}
})
StackNavigator.js
import React from 'react';
//설치한 스택 네비게이션 라이브러리를 가져옵니다
import { createStackNavigator } from '@react-navigation/stack';
//페이지로 만든 컴포넌트들을 불러옵니다
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';
import AboutPage from '../pages/AboutPage';
import LikePage from '../pages/LikePage';
//스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용합니다
//그래서 이렇게 항상 상단에 선언하고 시작하는게 규칙입니다!
const Stack = createStackNavigator();
const StackNavigator = () =>{
return (
//컴포넌트들을 페이지처럼 여기게끔 해주는 기능을 하는 네비게이터 태그를 선언합니다.
//위에서 선언한 const Stack = createStackNavigator(); Stack 변수에 들어있는 태그를 꺼내 사용합니다.
//Stack.Navigator 태그 내부엔 페이지(화면)를 스타일링 할 수 있는 다양한 옵션들이 담겨 있습니다.
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "white",
borderBottomColor: "white",
shadowColor: "white",
height:100
},
headerTitleAlign: 'left',
headerTintColor: "#000",
headerBackTitleVisible: false
}}
>
{/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣습니다. 이 자체로 이제 페이지 기능을 합니다*/}
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
<Stack.Screen name="AboutPage" component={AboutPage}/>
<Stack.Screen name="LikePage" component={LikePage} />
</Stack.Navigator>
)
}
export default StackNavigator;
MainPage.js
import React, {useState, useEffect} from "react";
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
ScrollView,
SafeAreaView,
} from "react-native";
import { StatusBar } from "expo-status-bar";
import data from "../data.json";
import Card from "../components/Card";
import Loading from "../components/Loading";
const mainImg =
"https://storage.googleapis.com/sparta-image.appspot.com/lecture/main.png";
const cardImg =
"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3";
// 페이지 이동을 구현
// Stack.Screen 으로부터 MainPage 는 navigation과 route 를 인자로 전달받는다.
export default function MainPage({navigation, route}) {
const [state, setState] = useState([]);
const [ready, setReady] = useState(true);
const [cateState, setCateState] = useState([]);
useEffect(() => {
setTimeout(()=>{
// 헤더의 타이틀 변경
navigation.setOptions({
title: '나만의 꿀팁'
})
setState(data.tip)
setCateState(data.tip)
setReady(false)
}, 1000)
}, [])
const category = (cate) => {
if (cate == '전체보기') {
setCateState(state)
} else {
setCateState(state.filter((d) => {
return d.category == cate
}))
}
}
// 날씨
let todayWeather = 10 + 17;
let todayCondition = '흐림';
return ready ? <Loading /> : (
<SafeAreaView>
<ScrollView style={styles.container}>
<StatusBar style="black" />
{/* 타이틀 */}
{/* <Text style={styles.title}>나만의 꿀팁</Text> */}
<Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition}</Text>
<TouchableOpacity></TouchableOpacity>
{/* 메인 이미지 */}
<Image source={{ uri: mainImg }} style={styles.mainImage} />
{/* 탭 버튼 목록 */}
<ScrollView
horizontal
style={styles.btnContainer}
indicatorStyle={"white"}
>
<TouchableOpacity style={styles.btnAll} onPress={()=>{category('전체보기')}}>
<Text style={styles.textStyle}>전체보기</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn01} onPress={()=>{category('생활')}}>
<Text style={styles.textStyle}>생활</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn02} onPress={()=>{category('재테크')}}>
<Text style={styles.textStyle}>재테크</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn03} onPress={()=>{category('반려견')}}>
<Text style={styles.textStyle}>반려견</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn04} onPress={()=>{navigation.navigate('LikePage')}}>
<Text style={styles.textStyle}>꿀팁 찜</Text>
</TouchableOpacity>
</ScrollView>
{/* 카드 목록 */}
{/* 카드 컴포넌트 눌렀을 때 페이지가 이동될 수 있도록 navigation 을 넘겨준다.*/}
{cateState.map((content, i) => {
return <Card content={content} key={i} navigation={navigation} />;
})}
</ScrollView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
},
title: {
fontSize: 25,
marginTop: 20,
marginLeft: 20,
fontWeight: "bold",
},
weather: {
alignSelf: 'flex-end',
paddingRight: 20,
},
mainImage: {
width: "90%",
height: 200,
borderRadius: 5,
alignSelf: "center",
margin: 10,
},
btnContainer: {
margin: 20,
height: 60,
},
btnAll: {
backgroundColor: "#20b2aa",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn01: {
backgroundColor: "rgb(246, 204, 113)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn02: {
backgroundColor: "rgb(241, 156, 131)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn03: {
backgroundColor: "rgb(178, 223, 208)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
btn04: {
backgroundColor: "rgb(238, 150, 180)",
width: 100,
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
},
textStyle: {
color: "#fff",
},
});