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

如何在React Native中用动画实现状态更新时的屏幕滑动切换效果

React Native 实现问卷页右滑覆盖转场效果方案

现有代码问题排查

  • 动画映射错误:直接将0-1范围的动画值绑定到translateX属性,仅会产生1px位移,无法出现整屏滑入效果
  • 状态更新逻辑错误:先更新activeIndex再触发动画,会导致旧内容直接被替换,无法看到转场过程
  • 缺少双视图层级控制:要实现新内容覆盖旧内容的效果,需要同时保留新旧两个问题视图,控制前后层级和各自的位移属性

完整实现代码

import {
  View,
  Text,
  Button,
  Animated,
  Dimensions,
  StyleSheet
} from 'react-native'
import { useState, useRef } from 'react'

// 获取屏幕宽度作为动画偏移基准
const SCREEN_WIDTH = Dimensions.get('window').width
// 转场时长和React Navigation默认时长保持一致
const TRANSITION_DURATION = 300

const QuestionScreen = () => {
  const [activeIndex, setActiveIndex] = useState(0)
  // 存储上一个问题的索引,用于渲染退场的旧内容
  const [previousIndex, setPreviousIndex] = useState(null)
  // 动画值用ref存,不需要触发重渲染
  const slideAnim = useRef(new Animated.Value(0)).current

  const onClickNext = () => {
    // 防止动画过程中重复点击
    if (previousIndex !== null) return
    // 先存储当前索引作为待退场的旧内容索引
    setPreviousIndex(activeIndex)
    // 重置动画值为屏幕宽度,新内容初始在屏幕右侧外部
    slideAnim.setValue(SCREEN_WIDTH)
    // 更新为新的问题索引
    const newIndex = activeIndex + 1
    setActiveIndex(newIndex)
    // 启动滑入动画
    Animated.timing(slideAnim, {
      toValue: 0,
      duration: TRANSITION_DURATION,
      useNativeDriver: true,
    }).start(() => {
      // 动画结束后清空旧索引,释放资源
      setPreviousIndex(null)
    })
  }

  // 这里替换为你自己的问题文本获取逻辑
  const getQuestionText = (index) => {
    return `第${index + 1}题的问题内容`
  }

  return (
    <View style={styles.container}>
      {/* 渲染旧的问题内容(如果存在),在视图底层 */}
      {previousIndex !== null && (
        <View style={styles.questionContainer}>
          <Text>{getQuestionText(previousIndex)}</Text>
        </View>
      )}
      {/* 渲染新的问题内容,在视图顶层,绑定滑入动画 */}
      <Animated.View 
        style={[
          styles.questionContainer,
          { transform: [{ translateX: slideAnim }] }
        ]}
      >
        <Text>{getQuestionText(activeIndex)}</Text>
        {/* 你的下一步按钮 */}
        <Button title="下一步" onPress={onClickNext} />
      </Animated.View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: 'relative'
  },
  questionContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: '#fff', // 必须设置背景色,否则会透出下层内容
    padding: 20
  }
})

效果适配说明

  • 如果需要和React Navigation默认转场完全一致,可以给旧内容也添加位移动画,让旧内容随新内容滑入同步向左偏移20%屏幕宽度即可
  • 如果需要实现上一题的左滑入场效果,只需把动画初始值设置为-SCREEN_WIDTH即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:24:06