You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native启动页与主页面平滑过渡问题求助

解决React Native(Expo)启动页与主页面平滑过渡问题

问题分析

你的代码存在几个关键问题导致过渡失效:

  • 依赖冲突:同时安装了expo-splash-screen和react-native-splash-screen,两者功能重叠会引发异常
  • 动画未绑定视觉元素:Animated.Value(1)没有应用到任何视图的透明度样式,动画无法被感知
  • 过渡逻辑缺失:appIsReady为false时直接返回null,系统启动页仍在显示;准备完成后直接切换主页面,无中间过渡效果

解决方案步骤

1. 清理冲突依赖

移除react-native-splash-screen,基于Expo的项目仅需保留官方的expo-splash-screen:

expo uninstall react-native-splash-screen

同时删除package.json中对应的react-native-splash-screen依赖项。

2. 修改App.js实现平滑过渡

核心思路:创建与系统启动页视觉完全一致的自定义启动页组件,应用准备完成后,通过动画淡出该组件,同时隐藏系统启动页,实现无缝过渡。

修改后的完整代码:

import { StatusBar } from 'expo-status-bar';
import { Animated, StyleSheet, View, Image } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaProvider } from 'react-native-safe-area-context';

import HomeScreen from "./src/screens/HomeScreen";
import ProfileScreen from "./src/screens/ProfileScreen";
import AlertScreen from "./src/screens/AlertScreen";

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { useEffect, useState, useRef } from 'react';

import * as SplashScreen from "expo-splash-screen";

// 阻止系统自动隐藏启动页
SplashScreen.preventAutoHideAsync();

export default function App() {
  const [appIsReady, setAppIsReady] = useState(false);
  // 自定义启动页的透明度动画值,初始为1(完全显示)
  const splashOpacity = useRef(new Animated.Value(1)).current;
  const Tab = createBottomTabNavigator();

  const screenOptions = ({ route }) => ({
    tabBarIcon: ({ focused, color, size }) => {
      let iconName;
      if (route.name === "Home") {
        iconName = focused ? "ios-home" : "ios-home-outline";
      } else if (route.name === "Alert") {
        iconName = focused ? "ios-alert-circle" : "ios-alert-circle-outline";
      } else {
        iconName = focused ? "person-circle" : "person-circle-outline";
      }
      return <Ionicons name={iconName} size={size} color={color} />;
    },
    tabBarInactiveTintColor: 'gray',
  });

  // 模拟应用初始化操作(可替换为加载资源、请求接口等实际逻辑)
  useEffect(() => {
    const prepareApp = async () => {
      try {
        await new Promise(resolve => setTimeout(resolve, 1000));
      } catch (e) {
        console.warn(e);
      } finally {
        setAppIsReady(true);
      }
    };
    prepareApp();
  }, []);

  // 启动过渡动画并隐藏系统启动页
  useEffect(() => {
    if (appIsReady) {
      Animated.timing(splashOpacity, {
        toValue: 0,
        duration: 800,
        useNativeDriver: true,
      }).start(async () => {
        // 动画结束后隐藏系统启动页
        await SplashScreen.hideAsync();
      });
    }
  }, [appIsReady]);

  return (
    <SafeAreaProvider>
      {/* 主页面内容 */}
      <NavigationContainer>
        <Tab.Navigator initialRouteName="Home" screenOptions={screenOptions}>
          <Tab.Screen name="Home" component={HomeScreen} options={{ title: "首页" }} />
          <Tab.Screen name="Alert" component={AlertScreen} options={{ title: "告警", tabBarBadge: 3 }} />
          <Tab.Screen name="Profile" component={ProfileScreen} options={{ title: "我" }} />
        </Tab.Navigator>
        <StatusBar animated={true} style='light' />
      </NavigationContainer>

      {/* 自定义启动页,覆盖在主页面上方 */}
      {appIsReady ? (
        <Animated.View
          style={[
            styles.splashContainer,
            { opacity: splashOpacity, pointerEvents: 'none' }
          ]}
        >
          {/* 替换为你的系统启动页内容(logo、背景色等) */}
          <Image
            source={require('./assets/splash-logo.png')}
            style={styles.splashLogo}
          />
        </Animated.View>
      ) : null}
    </SafeAreaProvider>
  );
}

const styles = StyleSheet.create({
  splashContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: '#ffffff', // 替换为你的系统启动页背景色
    justifyContent: 'center',
    alignItems: 'center',
  },
  splashLogo: {
    width: 150,
    height: 150,
    resizeMode: 'contain',
  },
});

关键细节说明

  • 自定义启动页匹配:必须和系统启动页的视觉效果完全一致(背景色、logo位置等),避免过渡时出现视觉断层
  • 动画触发时机:appIsReady变为true时启动透明度动画,动画结束后再隐藏系统启动页,保证过渡流畅
  • pointerEvents控制:设置为none可确保动画过程中用户能与主页面交互,避免自定义启动页遮挡点击
  • 设备适配:用SafeAreaProvider包裹所有内容,适配刘海屏、底部安全区等设备特性

内容的提问来源于stack exchange,提问作者leo0807

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:22:20