React Native WebView如何设置Splash Image时长解决启动白屏
React Native 闪屏自定义时长+白屏问题修复方案
实现逻辑
核心采用双阶段闪屏承接方案,无需修改原生代码、无需引入第三方依赖:
- 原生默认闪屏自动消失后,由JS层渲染的、与原生闪屏视觉完全一致的全屏覆盖层立刻承接,完全阻断白屏露出路径
- 支持自定义闪屏最小展示时长,仅当「WebView页面加载完成」、「达到预设最小闪屏时长」两个条件同时满足时,才隐藏闪屏层展示WebView内容
- 同步修复原代码中重复声明App组件、未导入View组件、冗余测试代码的语法问题
可配置项
- 修改
MIN_SPLASH_DURATION参数值即可自定义闪屏最短显示时长,单位为毫秒,例如设置为3000即最少显示3秒 - 将闪屏覆盖层的背景色、图片资源替换为与原生端Splash Image完全一致的资源,即可做到原生闪屏与JS闪屏切换无视觉断层
修正后的完整app.js代码
import React, { useRef, useState, useCallback, useEffect } from "react"; import { BackHandler, Platform, StyleSheet, ActivityIndicator, View, Image } from "react-native"; import { WebView } from "react-native-webview"; // 闪屏最小显示时长(单位:毫秒),按需修改即可 const MIN_SPLASH_DURATION = 2500; // 替换为项目内实际的闪屏图资源,需和原生端闪屏图保持一致 const SPLASH_IMAGE = require("./splash.png"); export default function App() { const webView = useRef(); // 记录应用启动时间,用于计算闪屏实际显示时长 const appLaunchTime = useRef(Date.now()); const [canGoBack, setCanGoBack] = useState(false); // 控制闪屏覆盖层的显示状态 const [splashVisible, setSplashVisible] = useState(true); const handleBack = useCallback(() => { if (canGoBack && webView.current) { webView.current.goBack(); return true; } return false; }, [canGoBack]); useEffect(() => { BackHandler.addEventListener("hardwareBackPress", handleBack); return () => { BackHandler.removeEventListener("hardwareBackPress", handleBack); }; }, [handleBack]); // WebView加载完成回调,校验是否满足闪屏隐藏条件 const handleWebViewLoadEnd = useCallback(() => { const currentTime = Date.now(); const timePassed = currentTime - appLaunchTime.current; // 已达到最小显示时长则直接隐藏闪屏,否则等待剩余时长后再隐藏 if (timePassed >= MIN_SPLASH_DURATION) { setSplashVisible(false); } else { const remainTime = MIN_SPLASH_DURATION - timePassed; setTimeout(() => { setSplashVisible(false); }, remainTime); } }, []); const platformStyles = StyleSheet.create({ webView: Platform.OS === 'ios' ? { marginTop: 30, marginBottom: 40, flex: 1 } : { marginTop: 30, flex: 1 } }); return ( <View style={styles.rootContainer}> <WebView ref={webView} source={{ uri: "https://www.talesrunnerbestguild.co.kr/" }} style = {platformStyles.webView} onLoadProgress={(event) => setCanGoBack(event.nativeEvent.canGoBack)} onLoadEnd={handleWebViewLoadEnd} // 闪屏隐藏前WebView设为全透明,避免渲染过程露白 opacity={splashVisible ? 0 : 1} /> {/* 自定义闪屏覆盖层 */} {splashVisible && ( <View style={styles.splashContainer}> <Image source={SPLASH_IMAGE} style={styles.splashImage} resizeMode="cover" /> {/* 如需显示加载指示器可放开下方注释,不需要可直接删除 */} {/* <ActivityIndicator size="large" color="#0000ff" style={styles.loadingIndicator} /> */} </View> )} </View> ); } const styles = StyleSheet.create({ rootContainer: { flex: 1, }, splashContainer: { ...StyleSheet.absoluteFillObject, backgroundColor: '#ffffff', // 替换为和原生闪屏一致的背景色 justifyContent: 'center', alignItems: 'center', zIndex: 999, }, splashImage: { width: '100%', height: '100%', }, loadingIndicator: { position: 'absolute', bottom: 100, } });
使用说明
- 请将代码中
SPLASH_IMAGE的路径替换为项目内实际的闪屏图资源,修改splashContainer的背景色与原生闪屏背景色完全一致,保证切换过程无感知 - 闪屏显示时长直接修改
MIN_SPLASH_DURATION数值即可,例如需要显示5秒则改为5000 - 不需要加载指示器直接删除对应代码块即可,不影响核心逻辑运行
内容的提问来源于stack exchange,提问作者김준석
相关产品推荐
相关产品推荐

