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

如何实现React Native条件渲染组件的流畅过渡动画?

如何实现React Native条件渲染组件的流畅过渡动画?

你遇到的问题本质是直接挂载/卸载组件会触发瞬间布局重排,导致下方元素生硬位移。下面提供两种无需硬编码预留空间的可行方案:

方案一:用Animated库实现精准高度过渡

核心思路是始终渲染Tasks组件,通过动画控制外层容器的高度和透明度,从0平滑过渡到组件实际高度,避免直接插入/移除元素。

修改后的代码示例

Home.js:

import React, { useState, useRef, useEffect } from 'react';
import { View, Text, TouchableOpacity, Animated } from 'react-native';
import Tasks from './Tasks';

export default function Home() {
  const [showmore, setShowmore] = useState(false);
  // 动画变量:控制容器高度和透明度
  const taskHeight = useRef(new Animated.Value(0)).current;
  const opacity = useRef(new Animated.Value(0)).current;
  // 存储Tasks组件的实际高度
  const [actualTaskHeight, setActualTaskHeight] = useState(0);

  // 获取Tasks渲染后的真实高度
  const handleTaskLayout = (event) => {
    const { height } = event.nativeEvent.layout;
    setActualTaskHeight(height);
  };

  // 切换状态时触发动画
  useEffect(() => {
    Animated.parallel([
      Animated.timing(taskHeight, {
        toValue: showmore ? actualTaskHeight : 0,
        duration: 300, // 动画时长,可自定义
        useNativeDriver: false, // height动画不支持原生驱动
      }),
      Animated.timing(opacity, {
        toValue: showmore ? 1 : 0,
        duration: 300,
        useNativeDriver: true,
      }),
    ]).start();
  }, [showmore, actualTaskHeight]);

  return (
    <View>
      <View>
        <Text>Render Something </Text>
      </View>

      {/* 用Animated.View包裹Tasks,通过动画控制显示 */}
      <Animated.View
        style={{
          height: taskHeight,
          opacity,
          overflow: 'hidden', // 防止内容在高度为0时溢出
        }}
      >
        <Tasks onLayout={handleTaskLayout} />
      </Animated.View>

      <TouchableOpacity onPress={() => setShowmore(!showmore)}>
        <Text>{showmore ? '收起' : '展开'} Button</Text>
      </TouchableOpacity>
    </View>
  );
}

Tasks.js(只需传递onLayout事件):

import React from 'react';
import { View, Text } from 'react-native';

export default function Tasks({ onLayout }) {
  return (
    <View onLayout={onLayout}> 
      <Text> render some more things </Text>
      <Text> render some more things </Text>
      <Text> render some more things </Text>
      <Text> render some more things </Text>
      <Text> render some more things </Text>
    </View> 
  );
}

方案二:用LayoutAnimation实现全局布局过渡

如果不需要精准控制单个组件的动画,React Native内置的LayoutAnimation可以一键让所有布局变化自动带上过渡效果,代码极简。

修改后的代码示例

Home.js:

import React, { useState } from 'react';
import { View, Text, TouchableOpacity, LayoutAnimation, UIManager, Platform } from 'react-native';
import Tasks from './Tasks';

// Android需要手动开启布局动画实验特性
if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

export default function Home() {
  const [showmore, setShowmore] = useState(false);

  const toggleShowMore = () => {
    // 配置过渡动画,可选预设或自定义
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setShowmore(!showmore);
  };

  return (
    <View>
      <View>
        <Text>Render Something </Text>
      </View>

      {/* 正常条件渲染即可,LayoutAnimation会自动处理过渡 */}
      {showmore && <Tasks />}

      <TouchableOpacity onPress={toggleShowMore}>
        <Text>{showmore ? '收起' : '展开'} Button</Text>
      </TouchableOpacity>
    </View>
  );
}

方案对比

  • Animated方案:灵活度高,可自定义动画曲线、时长,甚至添加其他过渡效果;缺点是代码量稍大。
  • LayoutAnimation方案:代码极简,自动处理所有布局变化的动画;缺点是自定义程度低,Android需要额外配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:14:53