HarmonyOS 鸿蒙Next全局loading弹窗方法封装-自定义展示loading动画

发布于 1周前 作者 wuwangju 来自 鸿蒙OS

HarmonyOS 鸿蒙Next全局loading弹窗方法封装-自定义展示loading动画
<markdown _ngcontent-dht-c237="" class="markdownPreContainer">

在之前预览版本只能通过子窗口的形式来封装全局loading弹窗,还要使用到缓存,这就不符合我们的本意了,6月22号升级到beta1之后看了下文档可以通过getUIContext来进行弹窗展示了,下面就展示封装的方法

先引入ComponentContent,window,PromptAction,用于创建弹窗,AnyType是我自定义的ts的any类型,在ets引入ts,ts里声明一个AnyTypt为any

import { AnyType } from '[@common](/user/common)/types';
import { ComponentContent, window, PromptAction} from '@kit.ArkUI';
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

先创建一个loading动画组件,这个是我自定义的loading动画,也可以自行修改组件,定义自己喜欢的loading动画效果,API12多了一个onDidBuild生命周期,可以在组件加载后调用动画。

[@Extend](/user/Extend)(GridItem) function loadingIconItem(){
  .width('20lpx')
  .height('20lpx')
  .borderRadius('10lpx')
}
[@Component](/user/Component)
struct LoadingAnimation{
  [@State](/user/State) rotateAngle:number = 0
  build() {
    Grid(){
      GridItem()
        .backgroundColor('#6F94B3')
        .loadingIconItem()
  GridItem()
    .backgroundColor(<span class="hljs-string"><span class="hljs-string">'#0F4C81'</span></span>)
    .loadingIconItem()
  GridItem()
    .backgroundColor(<span class="hljs-string"><span class="hljs-string">'#B7C9D9'</span></span>)
    .loadingIconItem()
  GridItem()
    .backgroundColor(<span class="hljs-string"><span class="hljs-string">'#6F94B3'</span></span>)
    .loadingIconItem()
}
.rotate({
  x:<span class="hljs-number"><span class="hljs-number">0</span></span>,
  y:<span class="hljs-number"><span class="hljs-number">0</span></span>,
  z:<span class="hljs-number"><span class="hljs-number">1</span></span>,
  centerX: <span class="hljs-string"><span class="hljs-string">'50%'</span></span>,
  centerY: <span class="hljs-string"><span class="hljs-string">'50%'</span></span>,
  angle:<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.rotateAngle,
})
.width(<span class="hljs-string"><span class="hljs-string">'60lpx'</span></span>)
.height(<span class="hljs-string"><span class="hljs-string">'60lpx'</span></span>)
.columnsTemplate(<span class="hljs-string"><span class="hljs-string">'1fr 1fr'</span></span>)
.rowsTemplate(<span class="hljs-string"><span class="hljs-string">'1fr 1fr'</span></span>)

} onDidBuild(): void { animateTo({ duration: 1000, curve: Curve.Linear, iterations: -1, }, () => { this.rotateAngle = 360 })

} } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

然后再创建一个Builder,用于我们之后使用warpBuilder方法来定义全局Builder

class Params {
  text: string = ""
  constructor(text: string) {
    this.text = text;
  }
}
[@Builder](/user/Builder)
function loadingBuilder(params:Params){
  Column({space:'26lpx'}){
    LoadingAnimation()
    Text(params.text)
      .fontColor('#666666')
      .fontSize('24lpx')
  }
  .width('200lpx')
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

下面就是主菜了,定义了一个Loading类,定义show方法和hide方法

class Loading{
  private static loadingDialog:ComponentContent<AnyType> | null = null
  private static promptAction:PromptAction
  show(text:string = '加载中...'){
    window.getLastWindow(getContext()).then((windowClass)=>{
      const uiContext = windowClass.getUIContext()
      Loading.loadingDialog = new ComponentContent(uiContext, wrapBuilder(loadingBuilder),new Params(text));
      Loading.promptAction = uiContext.getPromptAction()
      Loading.promptAction.openCustomDialog(Loading.loadingDialog,
        {
          alignment:DialogAlignment.Center,
          isModal:true,
          autoCancel:false
        }
      )
  <span class="hljs-comment"><span class="hljs-comment">// const component =  uiContext.getComponentUtils()</span></span>
})

} hide(){ Loading.promptAction.closeCustomDialog(Loading.loadingDialog) } } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

最后导出

export new Loading()
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

这个方法不止可以封装全局loading,也可以以一样的方法封装全局弹窗 ,toast等方法,目前官方文档似乎也没有自定义展示图片的toast,不过用这个方法我们就可以完全自定义弹窗展示了,而不用去封装组件每个页面都引入,或者通过子窗口来变相封装。

</markdown>
11 回复

官方文档不建议这样用。🤣

cke_136.png

目前我要展示动画,好像只能这么用,其他的钩子好像行不通,有其他好用的方法可以提供下

有个问题,打开的弹框会被返回键关掉

可以在onWillDismiss里面拦截掉

不知道能不能获取得到按钮事件的回调?

什么按钮事件?

就比如弹窗里面有按钮,能否返回按钮的点击事件回调?

按照这个实现不会出现加载弹窗呢,且会提示[default] [Value:2545] JSNApi special value:0x2 checked
不起作用呢, 无法弹窗
有时开了关不掉

在HarmonyOS中封装全局Loading弹窗,并自定义展示动画,你可以通过继承Dialog类或使用Toast结合自定义布局来实现。对于全局使用,可以考虑使用服务(Service)或全局变量控制弹窗的显示与隐藏。自定义动画则需在布局文件中使用<animated-image><animated-vector>标签,或通过编程方式在Java/Kotlin代码中控制动画播放。确保在合适的位置(如Activity或Fragment的onResume/onPause)管理弹窗的显示与隐藏,以避免内存泄漏。如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部