프로젝트 본격적인 시작
맡은 파트 CSS
- 디테일 페이지와 속성페이지는 필수 구현사항이라 먼저 더미데이터를 이용해서 틀을 잡고 CSS를 꾸며주었다.
emotion/native
라이브러리를 사용해서 리액트에서 Styled Components
라이브러리를 사용한 것 처럼 CSS 작업을 하였다.
- Detail Screen에 비춰질 Component를 분리했다.
- Detail.jsx > Details.jsx > Item.jsx 컴포넌트 트리
import Details from "../components/Han/Details";
export default function Detail({ route: { params } }) {
return (
<>
<Details />
</>
);
}
import styled from "@emotion/native";
import DropShadow from "react-native-drop-shadow";
import { SCREEN_HEIGHT, SCREEN_WIDTH } from "../../utils";
import Item from "./Item";
export default function Details() {
return (
<>
<ScrollWrap>
<DetailImage
source={{
url: "https://ichef.bbci.co.uk/news/640/cpsprodpb/E172/production/_126241775_getty_cats.png",
}}
/>
<DropShadow
style={{
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 0.29,
shadowRadius: 4.65,
}}
>
<Item />
</DropShadow>
</ScrollWrap>
</>
);
}
const ScrollWrap = styled.View`
padding: 5%;
`;
const DetailImage = styled.Image`
height: ${SCREEN_HEIGHT / 3 + "px"};
width: ${SCREEN_WIDTH};
border-radius: 10%;
margin-bottom: 5%;
`;
import styled from "@emotion/native";
import { SCREEN_HEIGHT } from "../../utils";
export default function Item() {
return (
<DetailMainWrap>
<DetailTextWrap>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>품종</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>고양이</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>성별</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>여</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>나이</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>2019(년생)</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>체중</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>5kg</DetailTextContent>
</DetailTextBox>
<DetailTextBox style={{ marginBottom: 20 }}>
<DetailTextTItleBox>
<DetailTextTitle>색상</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>귀여운 색</DetailTextContent>
</DetailTextBox>
</DetailTextWrap>
<DetailTextWrap>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>공고번호</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>서울-xx-xxxx-xxxx</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>유기번호</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>xxxxxxxxxxxxxxxx</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>상태</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>보호중</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>접수일</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>2022-12-10</DetailTextContent>
</DetailTextBox>
<DetailTextBox style={{ marginBottom: 20 }}>
<DetailTextTItleBox>
<DetailTextTitle>공고시작일</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>2022-12-10</DetailTextContent>
</DetailTextBox>
</DetailTextWrap>
<DetailTextWrap>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>공고번호</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>서울-xx-xxxx-xxxx</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>유기번호</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>xxxxxxxxxxxxxxxx</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>상태</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>보호중</DetailTextContent>
</DetailTextBox>
<DetailTextBox>
<DetailTextTItleBox>
<DetailTextTitle>접수일</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>2022-12-10</DetailTextContent>
</DetailTextBox>
<DetailTextBox style={{ marginBottom: 20 }}>
<DetailTextTItleBox>
<DetailTextTitle>공고시작일</DetailTextTitle>
</DetailTextTItleBox>
<DetailTextContent>2022-12-10</DetailTextContent>
</DetailTextBox>
</DetailTextWrap>
</DetailMainWrap>
);
}
const DetailMainWrap = styled.View`
padding: 5% 7%;
background-color: white;
border-radius: 10%;
height: ${SCREEN_HEIGHT / 2 + "px"};
margin-bottom: 20px;
`;
const DetailTextWrap = styled.View`
border-bottom-width: 2px;
border-bottom-color: rgba(0, 0, 0, 0.1);
margin-bottom: 5%;
`;
const DetailTextBox = styled.View`
flex-direction: row;
text-align: center;
margin-bottom: 1%;
`;
const DetailTextTItleBox = styled.View`
width: 35%;
`;
const DetailTextTitle = styled.Text`
color: rgba(0, 0, 0, 0.3);
font-weight: bold;
/* margin-right: 20%; */
`;
const DetailTextContent = styled.Text`
font-weight: bold;
`;
Navigation
- 네비게이션을 사용한 스크린 이동
- 스크린 이동을 하기 위해서는 Stack.Navigator, Tabs.Navigator 컴포넌트 안에 Screen 컴포넌트로 감싸져야 한다.
name
props로 이동할 컴포넌트의 이름을 지정해 주고, component
props로 스크린 화면에 나타날 컴포넌트를 지정해준다.
- 보통 순서대로 처음 화면이 시작되지만
initialroutename
이라는 prpos를 사용해서 지정해 줄 수 있다.
- Detail 컴포넌트는 Tabs Navigation이 아닌데 밑에 Tabs바가 있어야 하는데, Stack.js를 Tabs에 한꺼번에 넣어서 해결하였다.
import React from "react";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { Text, TouchableOpacity } from "react-native";
import Stacks from "./Stacks";
import Tabs from "./Tabs";
const Stack = createNativeStackNavigator();
export default function Root() {
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="Tabs" component={Tabs} />
</Stack.Navigator>
);
}
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { Text, TouchableOpacity } from "react-native";
import Login from "../screens/Login";
import Detail from "../screens/Detail";
import Main from "../screens/Main";
import { AntDesign } from "@expo/vector-icons";
const Stack = createNativeStackNavigator();
export default function Stacks({ navigation: { goBack } }) {
return (
<Stack.Navigator
screenOptions={{
headerTitleAlign: "center",
headerLeft: () => (
<TouchableOpacity onPress={() => goBack()}>
<AntDesign name="left" size={24} color="black" />
</TouchableOpacity>
),
}}
>
<Stack.Screen
options={{
title: "유기동물",
}}
name="Main"
component={Main}
/>
<Stack.Screen
options={{
title: "정보",
}}
name="Detail"
component={Detail}
/>
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
);
}
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Stacks from "./Stacks";
import Favorites from "../screens/Favorites";
import Settings from "../screens/Settings";
import { SimpleLineIcons } from "@expo/vector-icons";
import { Ionicons } from "@expo/vector-icons";
import { Entypo } from "@expo/vector-icons";
import { AntDesign } from "@expo/vector-icons";
import { TouchableOpacity } from "react-native";
const Tab = createBottomTabNavigator();
export default function Tabs({ navigation: { goBack } }) {
return (
<Tab.Navigator
screenOptions={{
tabBarStyle: {
borderTopWidth: "1px",
borderTopColor: "E9E9E9",
backgroundColor: "#F19936",
},
tabBarActiveTintColor: "#ffffff",
tabBarInactiveTintColor: "#222222",
headerTitleAlign: "center",
headerLeft: () => (
<TouchableOpacity onPress={() => goBack()}>
<AntDesign
name="left"
size={24}
color="black"
style={{ marginLeft: 16 }}
/>
</TouchableOpacity>
),
}}
>
<Tab.Screen
options={{
headerShown: false,
tabBarIcon: ({ size }) => <Entypo name="github" size={size} />,
}}
name="Stacks"
component={Stacks}
/>
<Tab.Screen
options={{
title: "관심동물",
tabBarLabel: "관심동물",
tabBarIcon: ({ size }) => (
<Ionicons name="heart-outline" size={size} />
),
}}
name="Favorites"
component={Favorites}
/>
<Tab.Screen
options={{
title: "설정",
tabBarLabel: "설정",
tabBarIcon: ({ size }) => (
<SimpleLineIcons name="settings" size={size} />
),
}}
name="Settings"
component={Settings}
/>
</Tab.Navigator>
);
}