Skip to main content

Media & interactive Components

Image

  • 이미지를 표시하는 컴포넌트
  • uri를 이용한 네트워크 이미지 로드 및 로컬 이미지 지원
  • resizeMode를 사용하여 이미지 크기 조절 가능
  • 네트워크(API통신을 통한 이미지 호출) 및 로컬 이미지 지원
App.tsx
import { Image, View } from "react-native";
import cat from "./assets/cat.jpg";

export default function App() {
return (
<View style={{ flex: 1 }}>
<Image source={cat} style={{ width: 200, height: 200 }} />
</View>
);
}
src/types/image.d.ts
declare module "*.jpg";

Image

note

Image의 source를 이용하여 사진을 불러온다.
source에는 로컬 이미지, API통신을 통한 이미지 호출도 가능하다.
로컬 이미지를 호출 하는 다른 방법 중 하나는 require을 이용하는 것이다.

import { Image, View } from "react-native";

export default function App() {
return (
<View style={{ flex: 1 }}>
<Image
source={require("./assets/cat.png")}
style={{ width: 200, height: 200 }}
/>
</View>
);
}

React Native의 TypeScript버전은 이미지 확장자가 존재하지 않기 때문에
각 확장자에 대해 타입 모듈을 선언하는 방법으로 해결하면 된다.

Image 속성 정리

속성타입설명기본값
source{ uri: string } 또는 require("path")이미지 소스 지정 (네트워크 또는 로컬)필수
resizeMode"cover" "contain" "stretch" "repeat" "center"이미지 크기 조절 방식"cover"
styleStyleProp<ImageStyle>스타일 적용 (width, height 필수)undefined
onLoad() => void이미지가 로드될 때 실행할 함수undefined
onError(error) => void이미지 로드 실패 시 실행할 함수undefined
onLoadStart() => void이미지 로드 시작 시 실행할 함수undefined
onLoadEnd() => void이미지 로드 완료 후 실행할 함수undefined
onProgress(event) => void로드 중인 이미지의 진행 상태 반환undefined
fadeDurationnumberAndroid에서 이미지가 로드될 때의 페이드 효과 (ms)300
defaultSourceImageSourcePropType로드되기 전 표시할 기본 이미지 (iOS)undefined
blurRadiusnumber블러 효과 적용 (숫자가 클수록 흐려짐)0
tintColorstring이미지 색상 필터 적용undefined

  • resizeMode 속성 값 설명
설명
cover원본 비율을 유지하면서 컨테이너를 채움 (잘릴 수 있음)
contain원본 비율을 유지하면서 컨테이너 내에 맞춤 (잘리지 않음)
stretch원본 비율을 무시하고 컨테이너에 맞춤
center원본 크기를 유지하며 중앙 정렬
repeat이미지가 반복되도록 설정 (iOS only)

ImageBackground

  • 이미지를 배경으로 설정할 때 사용하는 컴포넌트
  • Image와 다르게 children을 포함 가능
  • Image와 같이 resizeMode를 사용하여 이미지 크기 조절 가능
App.tsx
import { ImageBackground, SafeAreaView, Text } from "react-native";
import cat from "./assets/cat.jpg";

export default function App() {
return (
<SafeAreaView
style={{
flex: 1,
}}
>
<ImageBackground source={cat} style={{ flex: 1 }}>
<Text style={{ color: "yellow", fontSize: 30 }}>Cat is Cute</Text>
</ImageBackground>
</SafeAreaView>
);
}
src/types/image.d.ts
declare module "*.jpg";

Image

note

<Image>태그와 다르게 <ImageBackground>태그는 배경으로 사용을 하며,
하위 태그에 다른 태그를 사용가능하다.

Image에서 작성된 속성과 동일하게 사용할 수 있다.

TouchableWithoutFeedback

  • 터치 이벤트를 감지하지만, 기본적인 피드백(애니메이션 효과 등)은 제공하지 않는 컴포넌트
  • 키보드 숨기기, 모달 외부 클릭 감지 등에 유용하게 사용
App.tsx
import {
View,
Image,
SafeAreaView,
TouchableWithoutFeedback,
} from "react-native";

export default function App() {
return (
<SafeAreaView style={{ flex: 1 }}>
<TouchableWithoutFeedback
onPress={() => console.log("이미지 외부 클릭!")}
>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<TouchableWithoutFeedback onPress={() => console.log("이미지 클릭!")}>
<Image
source={require("./assets/cat.jpg")}
style={{ width: "50%", height: "50%" }}
/>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
);
}

Image

note

이미지를 클릭할 경우, 이미지 클릭!이 출력,
이미지 밖을 클릭할 경우, 이미지 외부 클릭!이 출력된다.

TouchableWithoutFeedback을 이용하여 이벤트를 처리할 영역마다 감싸주면 된다.

info
App.tsx
import { useState } from "react";
import {
View,
SafeAreaView,
TouchableWithoutFeedback,
TextInput,
Keyboard,
Text,
} from "react-native";

export default function App() {
const [text, setText] = useState<string>("");

return (
<SafeAreaView style={{ flex: 1 }}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 10,
}}
>
<TouchableWithoutFeedback>
<TextInput
placeholder="값 입력"
onChangeText={(e) => setText(e)}
style={{
width: "50%",
borderWidth: 2,
borderColor: "#3498db",
borderRadius: 8,
}}
/>
</TouchableWithoutFeedback>
<Text>{text}</Text>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
);
}

Image

TextInput을 제외한 나머지 영역을 TouchableWithoutFeedback으로 감싼 후,
onPress에 Keyboard.dismiss를 설정하면,
사용자가 TextInput 외부를 터치할 때 키보드가 자동으로 닫힌다.

단, TouchableWithoutFeedback으로 감싸더라도 내부 요소(TextInput)가
터치 이벤트를 계속 받을 수 있도록 accessible={false} 를 추가하는 것이 좋다.

TouchableWithoutFeedback 속성 정리

속성명타입기본값설명
onPress() => void터치 이벤트 발생 시 실행할 함수
accessiblebooleantruefalse로 설정하면 내부 요소가 접근성 요소로 인식되지 않음 (이벤트 방해 방지)
disabledbooleanfalsetrue이면 터치 이벤트가 비활성화됨
hitSlop{ top, left, bottom, right }undefined터치 영역을 확장하거나 축소할 수 있음
onPressIn() => void터치가 시작될 때 실행되는 함수
onPressOut() => void터치가 끝났을 때 실행되는 함수
keyboardShouldPersistTaps"always" "handled" "never""never"터치 시 키보드 유지 여부 설정
  • React Native에서 화면 위에 새로운 뷰를 띄우는 컴포넌트
  • 팝업, 다이얼로그, 알림창 등을 만들 때 사용
App.tsx
import { useState } from "react";
import {
Modal,
View,
Image,
Button,
SafeAreaView,
TouchableWithoutFeedback,
} from "react-native";

export default function App() {
const [modalVisible, setModalVisible] = useState(false);

return (
<SafeAreaView
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<Button title="모달 열기" onPress={() => setModalVisible(true)} />
<Modal visible={modalVisible} animationType="slide" transparent={true}>
<TouchableWithoutFeedback
onPress={() => setModalVisible(!modalVisible)}
>
<View
style={{
flex: 1,
backgroundColor: "rgba(0,0,0,0.5)",
justifyContent: "center",
alignItems: "center",
}}
>
<TouchableWithoutFeedback>
<Image
source={require("./assets/cat.jpg")}
style={{ width: "50%", height: "50%" }}
/>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
</SafeAreaView>
);
}

Image

note

Modal의 열림/닫힘을 관리하기 위해 useState를 사용한다.
Modal은 React Native의 최상의 뷰에서 동작하는 독립적인 컴포넌트이기 때문에
Button과 같은 위치에 코드를 작성해도 동작에 문제가 없다.

Modal이 열린 후, Image영역 외의 배경을 클릭하면 Modal이 닫히도록 TouchableWithoutFeedback을 사용하였다.
이때, TouchableWithoutFeedback을 중첩하여 이미지 클릭 시에는 닫히지 않도록 처리했다.

속성명타입기본값설명
visiblebooleanfalse모달 표시 여부
animationType"none" "slide" "fade"none모달이 열릴 때 애니메이션 효과
transparentbooleanfalse모달 배경을 투명하게 설정
onRequestClose() => void안드로이드에서 뒤로 가기 버튼을 눌렀을 때 실행
presentationStyle"fullScreen" "pageSheet" "formSheet" "overFullScreen"fullScreeniOS에서 모달 스타일 지정

ActivityIndicator

  • 로딩 상태를 표시하는 기본적인 UI 컴포넌트
  • 실제 로딩을 표현하는 것이 아닌 시각적인 피드백만 제공
App.tsx
import { useState } from "react";
import { ActivityIndicator, View, Button } from "react-native";

export default function App() {
const [loading, setLoading] = useState(false);

return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 20,
}}
>
<View style={{ flexDirection: "row", gap: 20 }}>
<Button title="로딩 시작" onPress={() => setLoading(true)} />
<Button title="로딩 종료" onPress={() => setLoading(false)} />
</View>
{loading && <ActivityIndicator size={100} color="pink" />}
</View>
);
}

Image

note

위의 실행 화면과 같이 사용자에게 로딩 중임을 시각적으로 전달한다.
따라서, 데이터 로딩을 표현해야할 경우 useState 등을 활용하여 로딩 상태를 관리하면서 표시해야 한다.

ActivityIndicator 속성 정리

속성명타입기본값설명
animatingbooleantruetrue일 경우 애니메이션 활성화
size"small" "large" 혹은 number"small"인디케이터 크기 설정
colorstringgray인디케이터 색상 지정
hidesWhenStoppedbooleantrueanimating=false일 때 자동으로 숨김