HarmonyOS鸿蒙Next中overlay属性浮层和LoadingProgress()组件结合使用,导致LoadingProgress动画停顿

HarmonyOS鸿蒙Next中overlay属性浮层和LoadingProgress()组件结合使用,导致LoadingProgress动画停顿 环境:Deveco Studio 6.0.0版本,“targetSdkVersion”: “6.0.0(20)”

根据最佳实践

https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-component-nesting-optimization#section78181114123811

中提到,使用overlay属性优化,减少嵌套组件数量

将如下代码中Stack组件优化掉

@ComponentV2
struct PrivacyPage {
  // web组件是否加载中
  @Local isWebLoading: boolean = true;
  webViewController: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Stack() {
        Web({
          src: $rawfile('***.html'),
          controller: this.webViewController,
        })
          .onPageBegin(() => {
            this.isWebLoading = true
          })
          .onPageEnd(() => {
            this.isWebLoading = false
          })
        LoadingProgress()
          .width(60)
          .height(60)
          .enableLoading(this.isWebLoading)
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundColor($r('sys.color.background_secondary'))
    .padding(8)
  }
}

优化结果

@ComponentV2
struct PrivacyPage {
  // web组件是否加载中
  @Local isWebLoading: boolean = true;
  webViewController: webview.WebviewController = new webview.WebviewController();

  @Builder
  LoadingProgressOverlay() {
    LoadingProgress()
      .width(60)
      .height(60)
      .enableLoading(this.isWebLoading)
  }

  build() {
    Column() {
      Web({
        src: $rawfile('***.html'),
        controller: this.webViewController,
      })
        .onPageBegin(() => {
          this.isWebLoading = true
        })
        .onPageEnd(() => {
          this.isWebLoading = false
        })
      .width('100%')
      .height('100%')
      .overlay(this.LoadingProgressOverlay(), { align: Alignment.Center })
    }
    .height('100%')
    .width('100%')
    .backgroundColor($r('sys.color.background_secondary'))
    .padding(8)
  }
}

该优化结果会导致LoadingProgress的加载动画停顿,在当前API版本下是否有办法解决,或者有更好的优化方法?


更多关于HarmonyOS鸿蒙Next中overlay属性浮层和LoadingProgress()组件结合使用,导致LoadingProgress动画停顿的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

开发者你好

参考LoadingProgress文档说明:加载动效在组件不可见时停止,组件的可见状态基于onVisibleAreaChange处理,可见阈值ratios大于0即视为可见状态。

因为overlay属性对应的Builder结构不会上树,不在组件树上,所以LoadingProgress组件一直处于不可见状态,而LoadingProgress在不可见时动画会停止,所以出现了动画不动的现象。

【解决方案】

开发者可以参考以下方案,将LoadingProgress组件挂载到overlayManager上,通过overlayManager打开或者关闭动画。

示例demo如下:

import { webview } from '@kit.ArkWeb';
import { ComponentContent } from '@kit.ArkUI';

@Builder
function LoadingProgressOverlay() {
  LoadingProgress()
    .width(60)
    .height(60)
    .enableLoading(true)
    .onAppear(() => {
      console.log('onAppear');
    })
    .onVisibleAreaChange([0, 0.5], (isExpanding, value) => {
      console.log('', isExpanding, value);
    })
}

@Entry
@ComponentV2
struct Index {
  // web组件是否加载中
  @Local isWebLoading: boolean = true;
  webViewController: webview.WebviewController = new webview.WebviewController();

  @Builder
  LoadingProgressOverlay() {
    LoadingProgress()
      .width(60)
      .height(60)
      .enableLoading(this.isWebLoading)
      .onAppear(() => {
        console.log('', 'onAppear');
      })
      .onVisibleAreaChange([0, 0.5], (isExpanding, value) => {
        console.log('', isExpanding, value);
      })
  }

  build() {
    Column() {
      Web({
        src: '',
        controller: this.webViewController,
      })
        .onPageBegin(() => {
          this.isWebLoading = true;
          this.getUIContext().getOverlayManager().addComponentContent(new ComponentContent(this.getUIContext(), wrapBuilder(LoadingProgressOverlay)));
          this.getUIContext().getOverlayManager().showAllComponentContents();
        })
        .onPageEnd(() => {
          this.isWebLoading = false;
          this.getUIContext().getOverlayManager().hideAllComponentContents();
        })
        .width('100%')
        .height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundColor($r('sys.color.background_secondary'))
    .padding(8)
  }
}

更多关于HarmonyOS鸿蒙Next中overlay属性浮层和LoadingProgress()组件结合使用,导致LoadingProgress动画停顿的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,overlay属性创建的浮层与LoadingProgress组件结合使用时,可能导致动画停顿。这是因为overlay浮层可能阻塞了UI渲染线程,影响了LoadingProgress的动画流畅性。建议检查浮层的布局层级和渲染机制,确保动画组件能获得足够的渲染资源。

在HarmonyOS Next中,使用overlay属性结合LoadingProgress组件导致动画停顿,通常是因为overlay的浮层内容在状态更新时触发了不必要的重建。LoadingProgress的动画依赖于其内部状态的持续更新,而overlay中的@Builder方法在每次状态变化时会被重新调用,可能导致动画重置或卡顿。

解决方案:

  1. 使用@BuilderParam延迟构建
    LoadingProgress的构建移至@BuilderParam,避免每次状态更新时重新创建整个浮层内容。示例:

    [@ComponentV2](/user/ComponentV2)
    struct PrivacyPage {
      @Local isWebLoading: boolean = true;
      webViewController: webview.WebviewController = new webview.WebviewController();
    
      @BuilderParam overlayBuilder: () => void = this.loadingOverlay;
    
      @Builder
      loadingOverlay() {
        LoadingProgress()
          .width(60)
          .height(60)
          .enableLoading(this.isWebLoading)
      }
    
      build() {
        Column() {
          Web({
            src: $rawfile('***.html'),
            controller: this.webViewController,
          })
            .onPageBegin(() => { this.isWebLoading = true })
            .onPageEnd(() => { this.isWebLoading = false })
            .width('100%')
            .height('100%')
            .overlay(this.overlayBuilder, { align: Alignment.Center })
        }
        // ... 其他样式
      }
    }
    
  2. 分离动画控制与状态更新
    确保isWebLoading的状态变化不会触发overlay的完整重建。可以尝试将LoadingProgress的启用控制与浮层构建解耦,或使用@State修饰符配合条件渲染优化。

  3. 临时回退方案
    若上述方法无效,可暂时保留Stack组件,避免使用overlay。虽然嵌套层级增加,但能保证动画流畅性。后续可关注HarmonyOS版本更新,该问题可能在API优化后解决。

根本原因overlay@Builder方法在每次isWebLoading变化时被重新执行,导致LoadingProgress实例重建,动画中断。建议优先采用@BuilderParam或检查状态更新链路,减少不必要的重建。

回到顶部