Animated.ValueXY

2D 值用于驱动 2D 动画,例如平移手势。与普通的Animated.Value几乎相同的 API,但是可以多路复用。在内部包含两个常规的Animated.Value。

Animated.ValueXY 是 React Native 中用于处理二维动画的组件,它属于 React Native 的 Animated API。Animated.ValueXY 允许你同时控制一个元素的 X 和 Y 坐标,这在需要执行如平移、旋转等二维动画时非常有用。

基本用法

首先,确保你的项目中已经安装并正确引入了 react-native-reanimated。从 React Native 0.18 版本开始,Animated API 被重构为 react-native-reanimated,这是一个性能更优的替代品。

安装 react-native-reanimated

npm install react-native-reanimated
或者
yarn add react-native-reanimated

引入 reanimated 和 Animated.ValueXY

import { Animated } from 'react-native-reanimated';

使用 Animated.ValueXY

import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { useCode, useValue } from 'react-native-reanimated';

const AnimatedBox = () => {
  // 创建一个 Animated.ValueXY 对象
  const position = useValue({ x: 0, y: 0 });

  // 使用 useCode 来定义动画逻辑
  useCode(() => {
    return [
      // 例如,让元素向右下方移动
      Animated.event([{ nativeEvent: { translationX: position.x }, propagation: 'pointer' }], { useNativeDriver: false }),
      Animated.event([{ nativeEvent: { translationY: position.y }, propagation: 'pointer' }], { useNativeDriver: false }),
    ];
  }, [position]);

  return (
    <View style={styles.container}>
      <Animated.View style={{ transform: [{ translateX: position.x }, { translateY: position.y }] }}>
        {/* 子组件 */}
        <View style={styles.box} />
      </Animated.View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  box: {
    width: 50,
    height: 50,
    backgroundColor: 'blue',
  },
});

关键点解析:

  1. 创建 Animated.ValueXY: 通过 useValue({ x: 0, y: 0 }) 创建一个初始位置为 (0,0) 的二维动画值。这代表动画元素的初始 X 和 Y 坐标。

  2. 使用 useCodeAnimated.event: useCode 允许你定义动画的逻辑。这里使用 Animated.event 来监听触摸事件并更新 position 的 X 和 Y 值,从而实现动画效果。注意,为了使用触摸事件更新位置,你需要将 useNativeDriver 设为 false(除非你使用的是手势库如 react-native-gesture-handler 并正确配置了驱动)。如果你使用的是手势库,通常可以直接使用手势驱动的动画。

  3. 应用动画: 通过在 style 中使用 transform 属性,你可以将 position.xposition.y 应用到元素的 X 和 Y 坐标上,从而创建动画效果。

注意事项:

  • 当使用触摸事件或手势时,通常需要将 useNativeDriver 设为 false 或使用专门的库(如 react-native-gesture-handler)来处理手势驱动的动画。从 React Native 0.18 开始,原生驱动的动画在某些情况下可能不支持二维变换。
  • 对于更复杂的动画,如拖拽、滑动等,可以考虑使用专门的库如 react-native-gesture-handler 来简化手势处理和动画实现。

通过上述方式,你可以在 React Native 项目中有效地使用 Animated.ValueXY 来实现二维动画效果


实际案例演示:

这段React Native代码实现了一个应用程序状态监听器,其核心功能是实时监控和可视化显示应用在前台、后台或非活动状态之间的切换。代码通过React的响应式编程模型与React Native的AppState模块深度集成,构建了一个能够感知应用生命周期变化的智能组件。

在初始化阶段,组件使用useRef钩子创建了一个持久化的引用对象appState,用于存储当前的应用状态值。这个引用对象在整个组件生命周期内保持稳定,不会因为重新渲染而改变。同时,组件通过useState钩子建立了appStateVisible状态变量,这个变量专门用于驱动UI的重新渲染,确保界面始终与真实的应用状态保持同步。


import React, {useRef, useState, useEffect} from 'react';
import {AppState, StyleSheet, Text, View} from 'react-native';

const AppStateExample = () => {
  const appState = useRef(AppState.currentState);
  const [appStateVisible, setAppStateVisible] = useState(appState.current);

  useEffect(() => {
    const subscription = AppState.addEventListener('change', nextAppState => {
      if (
        appState.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        console.log('App has come to the foreground!');
      }

      appState.current = nextAppState;
      setAppStateVisible(appState.current);
      console.log('AppState', appState.current);
    });

    return () => {
      subscription.remove();
    };
  }, []);

  const getStateColor = () => {
    switch (appStateVisible) {
      case 'active':
        return '#4CAF50'; // Green for active state
      case 'background':
        return '#FF9800'; // Orange for background state
      case 'inactive':
        return '#F44336'; // Red for inactive state
      default:
        return '#2196F3'; // Blue for unknown state
    }
  };

  return (
    <View style={styles.container}>
      <Text style={[styles.stateText, { color: getStateColor() }]}>
        Current state is: {appStateVisible}
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5F5F5',
    padding: 20,
    borderRadius: 10,
  },
  stateText: {
    fontSize: 20,
    fontWeight: 'bold',
    textShadowColor: 'rgba(0, 0, 0, 0.2)',
    textShadowOffset: { width: 1, height: 1 },
    textShadowRadius: 2,
  },
});

export default AppStateExample;

useEffect钩子承担了事件监听的核心职责。它在组件挂载完成后立即执行,通过AppState.addEventListener方法注册一个状态变化监听器。这个监听器会捕获所有应用状态的变更事件,包括从后台切换到前台、从前台切换到后台,或是应用进入非活动状态等场景。监听器函数接收下一个状态值作为参数,并与当前状态进行比较分析,特别关注应用从非活动或后台状态重新回到活动状态的场景,这种场景通常意味着用户重新激活了应用。

在事件处理逻辑中,代码通过正则表达式匹配来检测状态变化的特定模式。当应用从inactive或background状态转变为active状态时,会在控制台输出相应的日志信息,这对于调试和用户行为分析非常有价值。每次状态变化时,appState引用和appStateVisible状态都会同步更新,确保数据的一致性。

视觉反馈方面,getStateColor函数根据当前的应用状态返回相应的颜色代码。活动状态用绿色表示,背景状态用橙色表示,非活动状态用红色表示,未知状态则使用蓝色作为默认值。这种颜色编码系统为用户提供了直观的状态识别方式,符合常见的状态指示器设计规范。

界面渲染采用了React Native的StyleSheet系统来定义样式。容器样式配置了弹性布局、居中对齐、背景色和内边距等属性,创建了一个美观的显示区域。文本样式则设置了合适的字体大小、粗细和阴影效果,增强了视觉层次感和可读性。


打包

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

在这里插入图片描述
最后运行效果图如下显示:

请添加图片描述

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐