@ List
** 3.1.5 이미지 사용하기
* 3.2 TextInput으로 사용자 키보드 입력받기
** 3.2.1 KeyboardAvodingvire로 키보드가 화면을 가리지 않게 하기
** 3.2.2 useState로 텍스트 상태 값 관리하기
** 3.2.3 커스텀 버튼 만들기
** 3.2.4 TextIput에 onSubmitEditing 및 returnKeyType 설정하기
* 3.3 정리
@ Note
1. 스타일링 단위
- ppi (pixel per inch) : 1inch에 몇 px이 들어갈 수 있는지 의미
- dpi (dots per inch) : ppi와 유사하며 인쇄물에서 사용하는 단위
- react native 스타일링 시 크기는 dp 로 설정
> dp (density-independent pixel) : 1inch당 픽셀 밀도에 따라 크기가 일관된 UI를 보여줄 수 있는 단위
dp = px * 160 / ppi
px = dp * ppi / 160
> ex)
iPhone 11 Pro 에서 너비 200 사이즈에 선명한 이미지 보여 줄 때
200 * 458 / 160 =572.5px 이미지 사용해야 선명함 --> circle@3x.png 사용
1) circle.png = 200px x 200px
2) circle@2x.png = 400px x 400px
3) circle@3x.png = 600px x 600px
2. assets > icons & images 다운
- reference : https://bit.ly/chapter-3-images
@ Result
# App. js
import React from 'react';
import {StyleSheet, KeyboardAvoidingView, Platform} from 'react-native';
import DateHead from './components/DateHead';
// for IOS StatusBar
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
import AddTodo from './components/AddTodo';
import Empty from './components/Empty';
function App() {
const today = new Date();
return (
<SafeAreaProvider>
<SafeAreaView edges={['bottom']} style={styles.block}>
<KeyboardAvoidingView
// behavior={Platform.OS === 'ios' ? 'padding' : undefined} // 삼항연산자 이용 시
behavior={Platform.select({ios: 'padding', android: undefined})}
style={styles.avoid}>
<DateHead date={today} />
<Empty />
<AddTodo />
</KeyboardAvoidingView>
</SafeAreaView>
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
block: {
flex: 1,
backgroundColor: 'white',
},
avoid: {
flex: 1,
},
});
export default App;
# components > AddTodo.js
import React, {useState} from 'react';
import {
View,
StyleSheet,
TextInput,
Image,
Platform,
TouchableOpacity,
TouchableNativeFeedback,
Keyboard,
} from 'react-native';
function AddTodo() {
const [text, setText] = useState('');
const onPress = () => {
setText('');
Keyboard.dismiss(); // button 눌렀을 시 키보드 사라짐
};
const button = (
<View style={styles.buttonStyle}>
<Image source={require('../assets/icons/add_white/add_white.png')} />
</View>
);
return (
<View style={styles.block}>
<TextInput
placeholder="할일을 입력하세요."
style={styles.input}
value={text}
onChangeText={setText}
onSubmitEditing={onPress} // Enter 눌렀을 시 키보드 사라짐
returnKeyType="done" // Enter 타입 지정
/>
{/* 삼항연산자 이용 */}
{/* {Platform.OS === 'ios' ? (
// ios : 터치 시 투명도 변경
<TouchableOpacity activeOpacity={0.5}>
<View style={styles.buttonStyle}>
<Image
source={require('../assets/icons/add_white/add_white.png')}
/>
</View>
</TouchableOpacity>
) : (
// android : 터치 시 물결
<View style={styles.circleWrapper}>
<TouchableNativeFeedback>
<View style={styles.buttonStyle}>
<Image
source={require('../assets/icons/add_white/add_white.png')}
/>
</View>
</TouchableNativeFeedback>
</View>
)} */}
{Platform.select({
ios: <TouchableOpacity onPress={onPress}>{button}</TouchableOpacity>,
android: (
<View style={styles.circleWrapper}>
<TouchableNativeFeedback onPress={onPress}>
{button}
</TouchableNativeFeedback>
</View>
),
})}
</View>
);
}
const styles = StyleSheet.create({
block: {
backgroundcolor: 'white',
height: 64,
paddingHorizontal: 16, // 좌우 여백
bordercolor: '#bdbdbd',
borderTopWidth: 1,
borderBottomWidth: 1,
alignItems: 'center', //상하 정렬
flexDirection: 'row',
},
input: {
flex: 1, // TextInput 란 확장
fontSize: 16,
paddingVertical: 8, // 상하 터치영역 확장
},
buttonStyle: {
alignItems: 'center',
justifyContent: 'center',
width: 48,
height: 48,
backgroundColor: '#26a69a',
borderRadius: 24,
},
circleWrapper: {
overflow: 'hidden', // 지정한 영역 외 바깥 영역 숨김
borderRadius: 24,
},
});
export default AddTodo;
# components > DataHead.js
import React from 'react';
import {View, Text, StyleSheet, StatusBar} from 'react-native';
// for IOS StatusBar
import {useSafeAreaInsets} from 'react-native-safe-area-context';
function DateHead() {
const d = new Date();
const year = d.getFullYear();
const month = d.getMonth() + 1; // getMonth 범위 : 0 ~ 11 까지
const day = d.getDate();
const formatted = `${year}년 ${month}월 ${day}일`;
const {top} = useSafeAreaInsets();
return (
<>
<View style={[styles.statusBarPlaceholder, {height: top}]} />
<StatusBar backgroundColor="#26a69a" barStyle="light-content" />
<View style={styles.block}>
{/* <Text style={styles.dateText}>{formatted}</Text> */}
<Text style={styles.dateText}>
{year}년 {month}월 {day}일
</Text>
</View>
</>
);
}
const styles = StyleSheet.create({
statusBarPlaceholder: {
backgroundColor: '#26a69a',
},
block: {
padding: 16,
backgroundColor: '#26a69a',
},
dateText: {
fontSize: 24,
color: 'white',
},
});
export default DateHead;
# components > Empty.js
import React from 'react';
import {View, Text, Image, StyleSheet} from 'react-native';
function Empty() {
// const source = {uri: 'https://via.placeholder.com/150'};
return (
<View style={styles.block}>
{/* <Image
source={require('../assets/images/circle.png')}
style={styles.image}
resizeMode="cover"
/> */}
{/* <Image source={source} style={styles.image} resizeMode="cover" /> */}
<Image
source={require('../assets/images/young_and_happy.png')}
style={styles.image}
resizeMode="cover"
/>
<Text style={styles.description}>할일이 없습니다.</Text>
</View>
);
}
const styles = StyleSheet.create({
block: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
image: {
width: 240,
height: 179,
marginBottom: 16,
},
description: {
fontSize: 24,
color: '#9e9e9e',
},
});
export default Empty;
'React Native > React Native_study' 카테고리의 다른 글
[리액트 네이티브를 다루는 기술 #6] 4장 할일 목록 만들기2 (p.179 ~ 214) (0) | 2021.12.24 |
---|---|
[리액트 네이티브를 다루는 기술 #5] 4장 할일 목록 만들기2 (p.161 ~ 178) (0) | 2021.12.23 |
[리액트 네이티브를 다루는 기술 #3] 3장 할일 목록 만들기1 (p.109 ~ 132) (0) | 2021.12.20 |
[리액트 네이티브를 다루는 기술 #2] 2장 컴포넌트 (p.99 ~ 108) (1) | 2021.12.20 |
[리액트 네이티브를 다루는 기술 #1] 2장 컴포넌트 (p. 70 ~ 98) (0) | 2021.12.20 |