앱의 폰트를 바꿔보자.
우선 사용하고자 하는 폰트 파일을 assets/font 폴더에 모아둔다.
터미널 창을 열어 다음과 같은 명령어를 입력한다.
npx expo install expo-font // 폰트 설정 패키지
npm i react-native-global-props --save // 특정 컴포넌트의 props 전역으로 설정하는 패키지
npm install --save-dev @types/react-native-global-props // react-native-global-props의 타입 정보
이제 App.tsx 파일로 돌아와 임포트 문을 추가하고,
import * as Font from "expo-font";
import { setCustomText } from "react-native-global-props";
아래와 같이 useEffect문을 작성해주면-
export default function App() {
const [fontLoaded, setFontLoaded] = useState(false); // 폰트 로드 상태
useEffect(() => {
// loadFonts 함수 작성
async function loadFonts() {
// 경로와 파일명에 유의할 것
await Font.loadAsync({
poppins100: require('./assets/fonts/Poppins-Thin.ttf'),
poppins200: require('./assets/fonts/Poppins-ExtraLight.ttf'),
poppins300: require('./assets/fonts/Poppins-Light.ttf'),
poppins400: require('./assets/fonts/Poppins-Regular.ttf'),
poppins500: require('./assets/fonts/Poppins-Medium.ttf'),
poppins600: require('./assets/fonts/Poppins-SemiBold.ttf'),
poppins700: require('./assets/fonts/Poppins-Bold.ttf'),
poppins800: require('./assets/fonts/Poppins-ExtraBold.ttf'),
poppins900: require('./assets/fonts/Poppins-Black.ttf'),
});
const customTextProps = {
style: {
fontFamily: "poppins400", // 디폴트 폰트. 위 loadFonts 함수에서 선언한 것과 이름이 일치해야 한다.
},
};
setCustomText(customTextProps); // Text 컴포넌트의 스타일을 전역으로 설정
setFontLoaded(true);
}
loadFonts();
}, []);
return <Screen />; // 보여줄 스크린 컴포넌트
}
앞으로 모든 Text 컴포넌트의 기본 폰트가 "poppins400"으로 명시한 파일과 일치하는 폰트로 설정된다.
만일 특정 컴포넌트에서 폰트 두께를 바꾸고 싶다면, 해당 컴포넌트에서 스타일링을 수정한다.
iOS에서는 오류 메세지가 없지만, 안드로이드 환경에서 아래 에러가 나타났다.
fontFamily "poppins300" is not a system font and has not been loaded through expo-font.
expo-font를 사용하여 폰트를 비동기적으로 로드하는 과정에서 미처 로드되지 않은 문제일 수 있다.
로드가 끝나지 않은 경우에 대해 처리를 해주도록 한다.
SplashScreen API를 통해 구현했다.
SplashScreen이란?
소위 말하는 로딩 화면이다.
앱의 화면 이동 중, 또는 리소스 다운로드 등 로딩 시간이 필요한 경우 나타나는 화면을 말한다.
SplashScreen 설치
npm install expo-splash-screen
기본적인 사용법은 아래와 같다.
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import * as SplashScreen from 'expo-splash-screen';
export default function App() {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
async function fetchData() {
await SplashScreen.preventAutoHideAsync(); // 스플래시 화면 자동 숨김 방지
// 서버에서 데이터 불러오는 작업 등 처리
await new Promise(resolve => setTimeout(resolve, 3000)); // 3초 딜레이
// 로딩 후 플래시 화면 숨기기
setIsLoading(false);
await SplashScreen.hideAsync();
}
fetchData();
}, []);
if (isLoading) {
return null; // 로딩 중일 때는 스플래시 화면 유지
}
return (
<View>
<Text>데이터가 로드 성공</Text>
</View>
);
}
SplashScreen.preventAutoHideAsync()
기본적으로 SplashScreen은 앱이 로드되었을 때 자동으로 사라지게 된다.
그러나 폰트 또는 데이터 로드 등 시간이 걸리는 작업의 경우, 작업이 미처 끝나기도 전에 스크린이 사라질 수 있다.
이런 경우 SplashScreen.preventAutoHideAsync() 함수를 통해 작업이 완료될 때까지 스크린을 유지하고, 이후 수동으로 화면을 숨기는 것이다.
따라서 아래와 같이 최종 코드가 완성되었다.
import { useState, useEffect } from "react";
import * as Font from "expo-font";
import { setCustomText } from "react-native-global-props";
import { StyleSheet, View } from "react-native";
import CategoryScreen from "./screens/CatetgoryScreen"
import * as SplashScreen from 'expo-splash-screen';
// 스플래시 화면 자동 숨김을 방지
SplashScreen.preventAutoHideAsync();
export default function App() {
const [fontLoaded, setFontLoaded] = useState(false);
useEffect(() => {
async function loadFonts() {
try {
await Font.loadAsync({
poppins100: require('./assets/fonts/Poppins-Thin.ttf'),
poppins200: require('./assets/fonts/Poppins-ExtraLight.ttf'),
poppins300: require('./assets/fonts/Poppins-Light.ttf'),
poppins400: require('./assets/fonts/Poppins-Regular.ttf'),
poppins500: require('./assets/fonts/Poppins-Medium.ttf'),
poppins600: require('./assets/fonts/Poppins-SemiBold.ttf'),
poppins700: require('./assets/fonts/Poppins-Bold.ttf'),
poppins800: require('./assets/fonts/Poppins-ExtraBold.ttf'),
poppins900: require('./assets/fonts/Poppins-Black.ttf'),
});
const customTextProps = {
style: {
fontFamily: "poppins900",
},
};
setCustomText(customTextProps);
setFontLoaded(true);
// 폰트가 로드된 후 스플래시 화면 숨김
await SplashScreen.hideAsync();
} catch (error) {
console.warn("Error loading fonts", error);
}
}
loadFonts();
}, []);
if (!fontLoaded) {
// 폰트가 로드되지 않았을 때는 아무 것도 렌더링하지 않음 (스플래시 화면 유지)
return null;
}
return <Screen />;
}