在Expo React Native应用中实现启动页动画遇空白白屏问题
问题描述
在React Native Expo应用中尝试用expo-splash-screen库设置JSON格式的动画作为启动页,但启动后只显示空白白屏,而非预期动画。已确认JSON文件有效、路径正确,且将原GIF转为了JSON格式。
App.js 代码
import 'react-native-gesture-handler'; import React, { useCallback } from 'react' import { StyleSheet, Text, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { MyStack } from './routes/homeStack'; import { useFonts } from 'expo-font'; import * as SplashScreen from 'expo-splash-screen' export default function App() { const [ fontsLoaded ] = useFonts({ 'Sofia-Pro': require('./assets/Sofia_Pro_Regular.otf'), 'Helvetica-Neue': require('./assets/HelveticaNeue-Medium.otf'), 'NunitoSans': require('./assets/NunitoSans-Bold.ttf'), 'LatoRegular': require('./assets/Lato-Regular.ttf') }) const onLayoutRootView = useCallback(async () => { if (fontsLoaded) { await SplashScreen.preventAutoHideAsync(); setTimeout(async () => { await SplashScreen.hideAsync(); }, 3000); } }, [fontsLoaded]); if (!fontsLoaded) { return null; } return ( <NavigationContainer onLayout={onLayoutRootView}> <MyStack/> </NavigationContainer> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
app.config.js 代码
import "dotenv/config"; export default { expo: { name: "Gig Fort", slug: "gig-fort", version: "3.0.0", orientation: "portrait", icon: "./assets/icon.png", userInterfaceStyle: "light", splash: { image: "./assets/gigFort_splash_animation.json", resizeMode: "contain", // backgroundColor: "#ffffff", }, updates: { fallbackToCacheTimeout: 0, }, assetBundlePatterns: ["**/*"], android: { googleServicesFile: "./google-services.json", icon: "./assets/icon.png", package: "******", config: { googleMaps: { apiKey: "******" } }, versionCode: 3 }, web: { favicon: "./assets/favicon.png", }, extra: { firebaseApiKey: process.env.FIREBASE_API_KEY, eas: { projectId: "******", }, }, }, };
问题排查与解决方案
1. 核心问题:Expo默认启动页不支持JSON动画
Expo的splash配置仅支持静态图片格式(PNG/JPG等),无法直接解析JSON格式的Lottie动画。你把JSON文件填到splash.image里,系统无法识别,自然显示空白。
2. 正确实现Lottie动画启动页的步骤
第一步:安装Lottie依赖
执行命令安装lottie-react-native:
npx expo install lottie-react-native
第二步:修改App.js,手动渲染动画
放弃依赖Expo默认启动页,在字体加载完成前自行渲染Lottie动画:
import 'react-native-gesture-handler'; import React, { useCallback } from 'react' import { StyleSheet, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { MyStack } from './routes/homeStack'; import { useFonts } from 'expo-font'; import * as SplashScreen from 'expo-splash-screen' import LottieView from 'lottie-react-native'; export default function App() { const [fontsLoaded] = useFonts({ 'Sofia-Pro': require('./assets/Sofia_Pro_Regular.otf'), 'Helvetica-Neue': require('./assets/HelveticaNeue-Medium.otf'), 'NunitoSans': require('./assets/NunitoSans-Bold.ttf'), 'LatoRegular': require('./assets/Lato-Regular.ttf') }); // 初始化时阻止启动页自动隐藏 React.useEffect(() => { async function prepare() { await SplashScreen.preventAutoHideAsync(); } prepare(); }, []); const onLayoutRootView = useCallback(async () => { if (fontsLoaded) { setTimeout(async () => { await SplashScreen.hideAsync(); }, 3000); } }, [fontsLoaded]); // 字体未加载时显示Lottie动画 if (!fontsLoaded) { return ( <View style={styles.splashContainer}> <LottieView source={require('./assets/gigFort_splash_animation.json')} autoPlay loop={false} resizeMode="contain" /> </View> ); } return ( <NavigationContainer onLayout={onLayoutRootView}> <MyStack /> </NavigationContainer> ); } const styles = StyleSheet.create({ splashContainer: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
第三步:调整app.config.js的splash配置
把原来的JSON文件换成一张静态占位图(比如动画的第一帧PNG),避免启动初期的短暂空白:
splash: { image: "./assets/splash_placeholder.png", // 静态占位图 resizeMode: "contain", backgroundColor: "#ffffff", },
3. 额外注意事项
- 确保Lottie的JSON文件是标准Lottie格式,可以用Lottie预览工具验证。
- 修改配置后重启Expo开发服务器,避免缓存干扰。
- 如果动画播放异常,检查JSON文件路径是否正确(
assetBundlePatterns: ["**/*"]已确保所有资源被打包)。
内容的提问来源于stack exchange,提问作者Josh Simon
相关产品推荐
相关产品推荐

