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

如何在React Native中为登录/登出状态的导航栈切换添加平滑淡入淡出动画?

实现登录/登出状态切换时的淡入淡出导航动画

你当前通过条件渲染Stack.Screen切换导航栈的方式,本质是组件的挂载/卸载,不会触发React Navigation的导航过渡动画,所以需要调整实现逻辑,下面提供两种贴近你iOS原生实现的方案:

方案一:利用React Navigation导航重置+自定义过渡动画

这种方式通过reset动作切换根栈,同时配置导航过渡动画,符合React Navigation的设计逻辑:

import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useEffect } from 'react';

const Stack = createStackNavigator();

function App() {
  const navigationRef = useNavigationContainerRef();

  // 监听登录状态变化,重置导航栈
  useEffect(() => {
    const targetRoute = isLoggedIn ? 'HomeStack' : 'Auth';
    navigationRef.reset({
      index: 0,
      routes: [{ name: targetRoute }],
    });
  }, [isLoggedIn, navigationRef]);

  return (
    <NavigationContainer ref={navigationRef}>
      <Stack.Navigator screenOptions={{ headerShown: false }}>
        <Stack.Screen
          name="HomeStack"
          component={HomeStack}
          options={{
            // 自定义淡入淡出插值器
            cardStyleInterpolator: ({ current }) => ({
              cardStyle: {
                opacity: current.progress.interpolate({
                  inputRange: [0, 1],
                  outputRange: [0, 1],
                }),
              },
              // 关闭默认遮罩层
              overlayStyle: { opacity: 0 },
            }),
            // 配置动画时长,和你iOS代码的0.5秒对应
            transitionSpec: {
              open: { animation: 'timing', config: { duration: 500 } },
              close: { animation: 'timing', config: { duration: 500 } },
            },
          }}
        />
        <Stack.Screen
          name="Auth"
          component={AuthStack}
          options={{
            cardStyleInterpolator: ({ current }) => ({
              cardStyle: {
                opacity: current.progress.interpolate({
                  inputRange: [0, 1],
                  outputRange: [0, 1],
                }),
              },
              overlayStyle: { opacity: 0 },
            }),
            transitionSpec: {
              open: { animation: 'timing', config: { duration: 500 } },
              close: { animation: 'timing', config: { duration: 500 } },
            },
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

方案二:直接对根容器做动画(更贴近你的iOS实现)

这种方式和你Swift代码逻辑完全一致,直接给整个导航容器添加淡入淡出动画,适合完全替换根栈的场景:

import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Animated, useRef, useEffect } from 'react';

const Stack = createStackNavigator();

function App() {
  // 初始化动画值,根据当前登录状态设置初始透明度
  const opacityAnim = useRef(new Animated.Value(isLoggedIn ? 1 : 0)).current;

  // 登录状态变化时执行动画
  useEffect(() => {
    Animated.timing(opacityAnim, {
      toValue: isLoggedIn ? 1 : 0,
      duration: 500, // 和iOS代码的0.5秒匹配
      useNativeDriver: true, // 使用原生驱动提升动画性能
    }).start(({ finished }) => {
      // 动画结束后的回调,对应Swift里的completion
      if (finished) {
        // 可在此处添加后续逻辑
      }
    });
  }, [isLoggedIn]);

  return (
    <Animated.View style={{ flex: 1, opacity: opacityAnim }}>
      <NavigationContainer>
        <Stack.Navigator>
          {isLoggedIn ? (
            <Stack.Screen
              name='HomeStack'
              component={HomeStack}
              options={{ headerShown: false }}
            />
          ) : (
            <Stack.Screen
              name='Auth'
              component={AuthStack}
              options={{ headerShown: false }}
            />
          )}
        </Stack.Navigator>
      </NavigationContainer>
    </Animated.View>
  );
}

方案对比

  • 方案一:遵循React Navigation导航机制,适合需要保留导航栈状态、或后续有其他导航操作的场景。
  • 方案二:逻辑贴近原生iOS实现,直接操作根容器动画,代码简洁,适合完全切换根导航栈的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:50:57