HarmonyOS鸿蒙Next中ComponentV2组件下在promise.then中使用animateTo动画后没有过渡动画(动画异常),怎么回事?

HarmonyOS鸿蒙Next中ComponentV2组件下在promise.then中使用animateTo动画后没有过渡动画(动画异常),怎么回事? 分别使用了@ComponentV2和Component对官方的动画做修改

@ComponentV2中使用Promise.then的回调中使用动画没有过度效果 直接执行到了最终态

@Component中使用Promise.then的回调中使用动画是正常的

4 回复

【背景知识】

  • 自定义组件内的build还未执行,内部组件还未创建,动画时机过早,动画属性没有初值无法对组件产生动画。
  • 某些场景下,在状态管理V2中使用animateTo动画,会产生异常效果,具体可参考:在状态管理V2中使用animateTo动画效果异常

【解决方案】

在状态管理V2中,当使用@Param@Monitor修饰的状态变量发生变化时,系统会首先执行@Monitor绑定的方法。由于自定义组件内的build方法还未执行,内部组件还未创建,动画时机过早,导致动画属性没有初值,无法对组件产生动画效果。为了解决该问题,可以为动画添加setTimeout延时,确保内部组件创建完成后再执行动画。 代码示例如下:

// StateV2Page.ets
import { StateV2Loading } from '../views/StateV2Loading';

@Entry
@ComponentV2
struct StateV2Page {
  @Local message: string = '点击触发Loading';
  @Local isLoading: boolean = false;
  [@Param](/user/Param) animationDuration: number = 800;
  @Local loadingRotate: number = 360;

  build() {
    RelativeContainer() {
      Row() {
        Text(this.message)
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            this.isLoading = true
          })
        StateV2Loading({ isLoading: this.isLoading })
      }.justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
      .id("row")
      .alignRules({
        center: { anchor: '__container__', align: VerticalAlign.Center },
        middle: { anchor: '__container__', align: HorizontalAlign.Center }
      })
    }
    .height('100%')
    .width('100%')
  }
}
// StateV2Loading.ets
@ComponentV2
export struct StateV2Loading {
  [@Param](/user/Param) isLoading: boolean = false;
  [@Param](/user/Param) animationDuration: number = 800;
  @Local loadingRotate: number = 0;
  [@Monitor](/user/Monitor)('isLoading')
  startAnim(){
    // 在setTimeout内就可执行动画
    setTimeout(() => {
      animateTo({
        duration: this.animationDuration,
        curve: Curve.Linear,
        iterations: -1
      }, () => {
        this.loadingRotate = 360;
      });
    }, 10)
  }

  build() {
    Row() {
      Image($r('app.media.startIcon'))
        .width(16)
        .height(16)
        .rotate({ angle: this.loadingRotate })
        .animation({
          duration: this.animationDuration,
          curve: Curve.Linear,
          iterations: -1
        })
    }
  }
}

更多关于HarmonyOS鸿蒙Next中ComponentV2组件下在promise.then中使用animateTo动画后没有过渡动画(动画异常),怎么回事?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


目前某些场景下状态管理V2会和animateTo冲突,不建议在V2中使用animateTo。

具体可以参考:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overview#状态管理v1与v2能力对比

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-local#在状态管理v2中使用animateto动画效果异常

在HarmonyOS Next中,ComponentV2组件下在promise.then中使用animateTo动画后没有过渡动画,可能是因为动画的执行时机与Promise的异步回调未正确同步。animateTo需要在UI线程中执行,而promise.then的回调可能未及时触发UI更新,导致动画未正常播放。建议检查Promise的异步操作是否阻塞了UI线程,或考虑使用setTimeout等方式确保动画在UI更新后执行。

在HarmonyOS Next中,ComponentV2组件下在Promise.then中使用animateTo动画没有过渡效果的问题,可能是由于ComponentV2的生命周期管理和动画执行时机导致的。以下可能的原因和解决方案:

  1. ComponentV2的异步更新机制:ComponentV2可能采用了更激进的优化策略,导致在Promise.then回调中直接批量更新状态,跳过了动画过渡阶段。

  2. 动画执行时机问题:尝试在animateTo前添加一个微任务延迟:

promise.then(() => {
  Promise.resolve().then(() => {
    animateTo({...}, () => {...})
  })
}
  1. 状态更新方式差异:ComponentV2可能对状态变更的处理方式不同,确保在动画前完成所有状态更新:
promise.then(() => {
  this.setState({...}, () => {
    animateTo({...}, () => {...})
  })
}
  1. 检查动画参数:确认duration、curve等参数在两种组件中配置一致。

建议先在简单场景下验证动画基础功能,再逐步加入Promise逻辑进行调试。

回到顶部