0 基础入门React Native鸿蒙跨平台开发:LayoutAnimation为组件布局的变化添加平滑的动画效果

LayoutAnimation

当布局变化时,自动将视图运动到它们新的位置上。

一个常用的调用此 API 的办法是在状态更新前调用。

LayoutAnimation是 React Native 提供的一个强大的模块,用于为组件布局的变化(如大小、位置、可见性改变)添加平滑的动画效果。它的核心优势在于,你无需手动控制每个动画帧,只需声明布局变化,系统会自动处理动画过程。

核心工作原理

LayoutAnimation的工作原理基于“配置-触发”模式:

  1. 配置动画:在布局发生变化之前,调用LayoutAnimation.configureNext(config)来指定下一次布局动画的详细参数。
  2. 触发布局变化:调用this.setState()或其他方式触发组件的重新渲染和布局计算。
  3. 自动播放动画:React Native 在下一个渲染周期自动为所有受影响的组件播放配置好的动画,将它们从旧的布局平滑地过渡到新的布局。

主要方法与配置

  1. configureNext(config, onAnimationDidEnd)
    这是最常用的方法,用于配置下一次布局动画。
  • config(必需):一个配置对象,定义动画的细节。
  • onAnimationDidEnd(可选):动画结束时的回调函数,仅在 iOS 平台支持。

config对象的关键属性:

属性说明可选值
duration动画持续时间,单位毫秒。number
create组件创建时的动画配置。{ type, property, ... }
update组件更新时的动画配置。{ type, property, ... }
delete组件销毁时的动画配置。{ type, property, ... }

createupdatedelete对象本身也包含以下属性:

  • type: 动画类型。
  • property: 动画属性。
  • springDamping: 弹跳动画的阻尼系数(用于spring类型)。
  • initialVelocity: 初始速度(用于spring类型)。
  • delay: 动画延迟时间(单位毫秒)。
  1. 预设的动画类型 (LayoutAnimation.Types)
    LayoutAnimation内置了几种常用的动画类型:
  • spring: 弹性动画,带有物理弹跳效果。
  • linear: 线性动画,速度恒定。
  • easeInEaseOut: 缓入缓出动画,开始和结束时较慢,中间较快。
  • easeIn: 缓入动画,开始慢,逐渐加速。
  • easeOut: 缓出动画,开始快,逐渐减速。
  1. 预设的动画属性 (LayoutAnimation.Properties)
    定义了动画作用的样式属性:
  • opacity: 透明度。
  • scaleXY: X 和 Y 轴的缩放。
  1. 辅助方法
  • create(duration, type, property): 一个便捷方法,用于快速创建config对象。例如:LayoutAnimation.create(300, LayoutAnimation.Types.spring, LayoutAnimation.Properties.scaleXY)

使用步骤与最佳实践

基本使用流程

  1. 配置动画:在触发状态更新前,调用LayoutAnimation.configureNext()
  2. 更新状态:调用this.setState()改变影响布局的 state。
  3. (可选)平台适配:在 Android 上,需要启用实验性布局动画功能。
// 示例:点击按钮时,让一个视图放大_onPress(){// 1. 配置下一次布局动画LayoutAnimation.configureNext({duration:300,create:{type:LayoutAnimation.Types.spring,property:LayoutAnimation.Properties.scaleXY,},update:{type:LayoutAnimation.Types.easeInEaseOut,},});// 2. 触发布局变化this.setState({width:this.state.width+20,height:this.state.height+20,

真实案例演示:

这段React Native代码实现了一个可折叠的界面元素,其核心功能是通过状态驱动的布局动画来创建流畅的展开和收起效果。代码利用了React Native的LayoutAnimation系统,这是一种声明式的动画API,可以让开发者在不编写复杂动画逻辑的情况下实现平滑的界面过渡。

在组件初始化阶段,代码首先进行平台特性检测,专门针对Android平台启用实验性的布局动画功能。这是因为在React Native中,布局动画在某些Android版本上可能默认不可用,需要通过UIManager显式启用。这种平台适配机制确保了动画效果在不同操作系统上的一致性。

importReact,{useState}from"react";import{LayoutAnimation,Platform,StyleSheet,Text,TouchableOpacity,UIManager,View}from"react-native";if(Platform.OS==="android"&&UIManager.setLayoutAnimationEnabledExperimental){UIManager.setLayoutAnimationEnabledExperimental(true);}constApp=()=>{const[expanded,setExpanded]=useState(false);return(<View style={style.container}><TouchableOpacity onPress={()=>{LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);setExpanded(!expanded);}}><Text>Press me to{expanded?"collapse":"expand"}!</Text></TouchableOpacity>{expanded&&(<View style={style.tile}><Text>Idisappear sometimes!</Text></View>)}</View>);};conststyle=StyleSheet.create({tile:{background:"lightGrey",borderWidth:0.5,borderColor:"#d6d7da"},container:{flex:1,justifyContent:"center",alignItems:"center",overflow:"hidden"}});exportdefaultApp;

组件内部使用useState Hook来管理一个名为expanded的布尔状态,这个状态决定了界面元素当前是展开还是收起状态。当用户点击TouchableOpacity组件时,会触发一个精心设计的动画序列。首先调用LayoutAnimation.configureNext方法配置下一个动画帧,使用预设的spring动画效果,这种效果模拟了物理弹簧的运动特性,为界面交互增添了自然感。

在渲染逻辑中,代码使用了条件渲染技术。只有当expanded状态为true时,才会渲染包含"我有时会消失!"文本的tile视图。这种设计模式使得界面元素能够根据状态动态地出现和消失,而不是简单地隐藏或显示。

TouchableOpacity组件中的文本内容也根据expanded状态动态变化,显示"按下我以收起!“或"按下我以展开!”,为用户提供了清晰的交互指引。

样式系统通过StyleSheet.create方法定义,container样式配置了弹性布局属性,确保内容在屏幕上居中显示,同时通过overflow: "hidden"属性防止内容溢出。tile样式则设置了浅灰色背景和细边框,创建了清晰的视觉层次。

整个动画过程体现了现代移动应用交互设计的最佳实践。当用户点击按钮时,LayoutAnimation系统会自动计算起始状态和结束状态之间的差异,并生成平滑的过渡动画。这种机制与传统的逐帧动画不同,它更注重声明界面应该达到的最终状态,而不是详细描述如何达到那个状态。

这种实现方式不仅代码简洁,而且性能优化良好。通过利用React Native的原生动画能力,避免了在JavaScript线程中执行复杂的计算,从而确保了动画的流畅性,即使在性能较低的设备上也能保持良好的用户体验。


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。


最后运行效果图如下显示: