<SafeAreaView>
only for ios (해당 요소들을 핸드폰의 구조, 메뉴에 닿지않게 padding을 자동으로 넣어줌)
android 의 경우에는 자동으로padding 넣어주기
import {
StyleSheet, // CSS
Text,
TouchableWithoutFeedback, // 효과없음
TouchableOpacity, // 투명도 0되었다가 복구됨
TouchableHighlight, // 하이라이트됨
TouchableNativeFeedback, // 클릭한 곳으로부터 파장
View, // div와 같은 기능
Image,
SafeAreaView,
Button,
Alert,
Platform, // padding 주기 위해
StatusBar,
} from 'react-native';
Platform 가져와서 -> user가 어떤 플팻폼으로 앱을 사용하는지 쳌
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop:Platform.OS === 'android' ? 20 : 0,
},
});
그리고 StatusBar 사용해보기
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop:Platform.OS === 'android' ? StatusBar.currentHeight : 0,
},
});
버튼
return (
<SafeAreaView style={styles.container}>
<Button
color="orange" // iphone은 글자색이, 안드로이드는 백그라운드 색이 바뀜
title="Click me" onPress={()=>console.log('clicked')} />
</SafeAreaView>
);
버튼 alert
return (
<SafeAreaView style={styles.container}>
<Button
title="Click me"
onPress={()=>Alert.alert("My title", "My msg", [
{text:"Yes", onPress:()=>console.log('Yes')},
{text:"No", onPress:()=>console.log('No')},
])}
/>
</SafeAreaView>
);
버튼 prompt (현재 ios에서만 가능)
return (
<SafeAreaView style={styles.container}>
<Button
title="Click me"
onPress={()=>
Alert.prompt("My title", "My msg", text => console.log(text))
}
/>
</SafeAreaView>
);
StyleSheet 으로 빼서 css 사용하면 좋은 점 (css 는 아니고js임!)
-> 오타가 있을 때 알려준다.!
CSS 섞어서 함꼐 쓰기
return (
<SafeAreaView style={[styles.container,containerStyle]}>
<Button
title="Click me"
onPress={()=>console.log("button clicked")}
/>
</SafeAreaView >
);
}
const containerStyle = {backgroundColor:"orange"};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: "center",
alignItems: 'center'
},
});
{[ 1 , 2 ]} 요렇게도 쓰면 합쳐진다
styles는 해당 component 아래에 코드를 드대로 두는게 나을 수 있다. 모듈로 뺴고 하면 왔다갔다 하는 번거로움이 있다.
Dimensions
density-independent Pixels = Dips
physical Pixels = DIPs x Scale Factor
export default function App() {
console.log(Dimensions.get("screen"))
// window vs screen -> ios는 같고 오직 android에서만 다름 window가 조금더 작다
return (
<SafeAreaView style={styles.container}>
<View style={{
backgroundColor:'dodgerblue',
width:'50%',
height:70,
}}></View>
</SafeAreaView >
);
}
Detecting Orientation Changes
resizing according to components
app.json
"orientation": "portrait", // potrait vs landscape vs default (support both)
"icon": "./assets/icon.png",
"splash": {
터미널 hooks API 설치
npm i @react-native-community/hooks
app.js 에 import
import { useDimensions } from '@react-native-community/hooks';
console.log 찍어보기
import { useDimensions, useDeviceOrientation } from '@react-native-community/hooks';
export default function App() {
console.log(useDimensions())
console.log(useDeviceOrientation())
// window vs screen -> ios는 같고 오직 android에서만 다름 window가 조금더 작다
return (
<SafeAreaView style={styles.container}>
<View style={{
위의 useDeviceOrientation() API를 사용해서 height: 를 정해줄 것임 ! -> 폰을 옆으로 볼 때 파란 부분 (보통 동영상 볼 떄) 이 100% height으로 되도록 !
import { useDimensions, useDeviceOrientation } from '@react-native-community/hooks';
export default function App() {
const {landscape} = useDeviceOrientation();
// window vs screen -> ios는 같고 오직 android에서만 다름 window가 조금더 작다
return (
<SafeAreaView style={styles.container}>
<View style={{
backgroundColor:'dodgerblue',
width:'100%',
height: landscape ? "100%" : "30%"
}}></View>
</SafeAreaView >
);
}
Flex Box
import React from 'react';
import {
StyleSheet, // CSS
Text,
TouchableWithoutFeedback, // 효과없음
TouchableOpacity, // 투명도 0되었다가 복구됨
TouchableHighlight, // 하이라이트됨
TouchableNativeFeedback, // 클릭한 곳으로부터 파장
View, // div와 같은 기능
Image,
SafeAreaView,
Button,
Alert,
Platform, // padding 주기 위해
StatusBar,
Dimensions,
} from 'react-native';
import { useDimensions, useDeviceOrientation } from '@react-native-community/hooks';
export default function App() {
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
}}
>
<View
style={{
backgroundColor:"dodgerblue",
flex:2,
}}
/>
<View
style={{
backgroundColor:"gold",
flex:1,
}}
/>
<View
style={{
backgroundColor:"silver",
flex:1,
}}
/>
</View>
);
}
const containerStyle = { backgroundColor: "orange" };
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,
},
});
FlexDirection
export default function App() {
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
}}
>
<View
style={{
backgroundColor:"dodgerblue",
// flex:1,
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"gold",
// flex:1,
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"tomato",
// flex:1,
width:100,
height:100,
}}
/>
</View>
);
}
-> 3개의 Views를 감싸고 있는 View에 flexDirection : "row" 를 주면 된다.
export default function App() {
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
}}
>
flexDirection:"row" 수평으로 왼쪽 붙기
flexDirection:"row-reverse" 수평으로 오른쪽 붙기
flexDirection:"column" default
flexDirection:"column-reverse" 왼쪽 아래로 떨어진
LINING : jstifyContent, alignitems and alignSelf (box 가운데 넣기 )
row center
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
}}
>
column center
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"column",
justifyContent:"center",
}}
>
justifyContent:"flex-start" 왼쪽에 붙기
justifyContent:"flex-end" 오른쪽에 붙기
justifyContent:"flex-center" 중간으로
justifyContent:"space-around" 각 요소 따로따로
justifyContent:"space-evenly" 넓이 동일하게
justifyContent:"space-between" 양쪽 끝에 붙도록
alignItems
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"cneter",
}}
>
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"baseline",
}}
>
<View
style={{
backgroundColor:"dodgerblue",
// flex:1,
width:100,
height:300,
}}
/>
<View
style={{
backgroundColor:"gold",
// flex:1,
width:100,
height:200,
}}
/>
alignItems:"center" // 가운데 정렬
alignItems:"baseline" //요소 끝 부분 맞추기
alignItems:"flex-end" // 요소 bottom에서부터 시작
alignItems:"flex-start" // 요소 top으로부터 시작
alignItems:"stretch" // 쭉 늘리기
첫 번째 파랑색만 위에서부터 시작하기
alignItems -> container
alignSelf -> indivisual item
alignSelf : "flex-start"
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"center",
}}
>
<View
style={{
backgroundColor:"dodgerblue",
// flex:1,
width:100,
height:300,
alignSelf:"flex-start" //
}}
/>
FlexWrap and alignContent
export default function App() {
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"center",
}}
>
<View
style={{
backgroundColor:"dodgerblue",
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"gold",
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"tomato",
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"grey",
width:100,
height:100,
}}
/>
<View
style={{
backgroundColor:"yellow",
width:100,
height:100,
}}
/>
</View>
);
}
container View 에 flexWrap:"wrap"을 주면 두번째 사진처럼 된다.
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"center",
flexWrap:"wrap",
}}
alignItems:'center'의 의미는 가운데인데 어떤 요소들이 존재할 때의 가운데임
View 1, 4 번의 height를 높여보면 세번째 사진처럼 됨 (center가 맞긴 하다)
모든걸 수직에서 가운데에 놓고 싶다면 다른 property를 사용한다. => alignContent
return(
<View
style={{
backgroundColor:"#fff",
flex:1,
flexDirection:"row",
justifyContent:"center",
alignItems:"center",
alignContent:"center",
flexWrap:"wrap",
}}
>
* alignItems: 각 line의 content 정렬
* alignContent 전체 content 들 정렬 / 꼭 Wrap 이 있어야 가능
FlexBasis, FlexFrow and FlexShrink
<View
style={{
backgroundColor:"dodgerblue",
flexBasis:100, // width: or height
flexGrow:1,
width:100,
height:100,
}}
/>
flexBasis : width & height 둘 다 가능
flexGrow : 1, --> 전체 비율 100% 까지 내용이 차게됨 == flex 와 동일하나 flex:1을 주었을 떄는 자동으로 고쳐지지않고 rr 새로고침을 해야함
flexGros <-> flexShrink
Absolute and Relative Positioning
<View
style={{
backgroundColor:"gold",
width:100,
height:100,
left:20
}}
/>
left:20
right:20
top:20
bottom:20
각 20px 씩 움직임
abolute = absolute position value
<View
style={{
backgroundColor:"gold",
width:100,
height:100,
top:20,
left:20,
position:"absolute",
}}
absolute 는 해당 요소가 절대 값을 가짐
relative 는 다른 요소들은 그대로고 해당 요소만 그 자리에서 값 이동이 됨
Image
const Main = ()=>{
return(
<>
<SafeAreaView style={styles.container}>
<Text>I am Main</Text>
<Image source={require('../assets/cat.jpg')}></Image>
</SafeAreaView>
</>
)
}
인터넷에서 가져오는 image 첨부 방법
두 개 합친 것
Exercises
1) 배경 이미지 넣기 / button 두 개 추가
App.js 에 연결된 welcomeScreen.jsx
import React from 'react'
import { ImageBackground, StyleSheet, View } from 'react-native'
const WelcomeScreen = (props) => {
return (
<>
<ImageBackground
style={styles.background}
source={require('../assets/cat.jpg')}
>
<View style={styles.loginButton}></View>
<View style={styles.registerButton}></View>
</ImageBackground>
</>
)
}
const styles = StyleSheet.create({
background:{
flex:1,
justifyContent:'flex-end' // 요 하나 추가하면 loginbutton 을 아래로 보냄
},
loginButton:{
width:'100%',
height:70,
backgroundColor:'#fc5c65',
},
registerButton:{
width:'100%',
height:70,
backgroundColor:'#4ecdc4',
}
})
export default WelcomeScreen
2) 아이콘 추가
지금 justifyContent:'flex-end' 이므로 안에 아이콘을 넣어도 아래에 붙게 됨 -> position:absolute 로 이동시키기
import React from 'react'
import { ImageBackground, StyleSheet, View, Image } from 'react-native'
const WelcomeScreen = (props) => {
return (
<>
<ImageBackground
style={styles.background}
source={require('../assets/cat.jpg')}
>
<Image source={require('../assets/favicon.png')} style={styles.logo}></Image>
<View style={styles.loginButton}></View>
<View style={styles.registerButton}></View>
</ImageBackground>
</>
)
}
const styles = StyleSheet.create({
background:{
flex:1,
justifyContent:'flex-end',
alignItems:'center', // 로고 중앙정렬
},
loginButton:{
width:'100%',
height:70,
backgroundColor:'#fc5c65',
},
registerButton:{
width:'100%',
height:70,
backgroundColor:'#4ecdc4',
},
logo:{
width:100,
height:100,
position:'absolute',
top:70, // logo absolute로 위에서 70px 만큼 띄우고
// 중앙 정렬은 요 element의 부모 ele에 가서 alignItems:'center'
}
})
export default WelcomeScreen
3) Test 추가 -> 아이콘 Image + Text를 함께 View tag 에 놓고 중앙 정렬
import React from 'react'
import { ImageBackground, StyleSheet, View, Image, Text } from 'react-native'
const WelcomeScreen = (props) => {
return (
<>
<ImageBackground
style={styles.background}
source={require('../assets/cat.jpg')}
>
<View style={styles.logoContainer}>
<Image source={require('../assets/favicon.png')} style={styles.logo}></Image>
<Text>Sell what you don't need</Text>
</View>
<View style={styles.loginButton}></View>
<View style={styles.registerButton}></View>
</ImageBackground>
</>
)
}
const styles = StyleSheet.create({
background: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
loginButton: {
width: '100%',
height: 70,
backgroundColor: '#fc5c65',
},
registerButton: {
width: '100%',
height: 70,
backgroundColor: '#4ecdc4',
},
logo: {
width: 100,
height: 100,
},
logoContainer:{
position: 'absolute',
top: 70,
alignItems:'center',
}
})
export default WelcomeScreen
4) ViewImageScreen 두 번째 Screen 만들기
app.jsx에 ViewImageScreen.jsx import and return
import React from 'react';
import {Image, StyleSheet} from 'react-native';
function viewImageScreen(props) {
return (
<Image source={require('../assets/me.jpg')} style={styles.image}></Image>
);
}
const styles = StyleSheet.create({
image:{
width:'100%',
height:'100%',
}
})
export default viewImageScreen;
width, height : 100% 으로 해도 사진이 짤린다 -> resize mode 때문!
function viewImageScreen(props) {
return (
<Image
resizeMode="contain"
source={require('../assets/me.jpg')}
style={styles.image}>
</Image>
);
}
resizeMode="contain"을 하면 오른쪽 처럼 이미지 전체가 나온다.
배경 검정색으로 만들기 - > 새로운 View로 감싸고 styles 추가 , flex = 1 으로 전체 감싸기
import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
function viewImageScreen(props) {
return (
<View style={styles.container}>
<Image
resizeMode="contain"
source={require('../assets/me.jpg')}
style={styles.image}>
</Image>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor:'black',
flex:1,
},
image: {
width: '100%',
height: '100%',
}
})
export default viewImageScreen;
5) 버튼 만들기
import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
function viewImageScreen(props) {
return (
<View style={styles.container}>
<View style={styles.closeIcon}></View>
<View style={styles.deleteIcon}></View>
<Image
resizeMode="contain"
source={require('../assets/me.jpg')}
style={styles.image}>
</Image>
</View>
);
}
const styles = StyleSheet.create({
closeIcon:{
width:50,
height:50,
backgroundColor:'#fc5c65',
position:'absolute',
top:40,
left:30,
},
deleteIcon:{
width:50,
height:50,
backgroundColor:'#4ecdc4',
position:'absolute',
top:40,
right:30,
},
container: {
backgroundColor:'black',
flex:1,
},
image: {
width: '100%',
height: '100%',
}
})
export default viewImageScreen;
6) 색상들 담은 파일로 따로 빼기
config 폴더 생성 > colors.js 파일 생성
export default {
primary:'#fc5c65',
secondary:'#4ecdc4',
black : '#000'
}
ViewImageScreen.js 에서 해당 색상 사용하기 -> 코드가 깔끔해짐 / 기억할 때 좋을 듯
import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
import colors from '../config/colors'
function viewImageScreen(props) {
return (
<View style={styles.container}>
<View style={styles.closeIcon}></View>
<View style={styles.deleteIcon}></View>
<Image
resizeMode="contain"
source={require('../assets/me.jpg')}
style={styles.image}>
</Image>
</View>
);
}
const styles = StyleSheet.create({
closeIcon:{
width:50,
height:50,
backgroundColor:colors.primary,
position:'absolute',
top:40,
left:30,
},
deleteIcon:{
width:50,
height:50,
backgroundColor:colors.secondary,
position:'absolute',
top:40,
right:30,
},
container: {
backgroundColor:colors.black,
flex:1,
},
image: {
width: '100%',
height: '100%',
}
})
export default viewImageScreen;
references
https://www.youtube.com/watch?v=0-S5a0eXPoc&t=6024s
'React + React Native + Expo' 카테고리의 다른 글
[React Native expo] chatting app 만들기 tutorial (0) | 2021.08.02 |
---|---|
[React] 리액트 CRUD (0) | 2021.07.31 |
[React 연습 5일차] 리액트 TicTacToe Game 구현 with Hooks API (0) | 2021.07.14 |
[React 연습 4일차] 리액트 TicTacToe Game 구현 (0) | 2021.07.05 |
[React 연습 3일차] 리액트 TicTacToe Game 구현 (0) | 2021.07.05 |