鸿蒙自定义Toast提示

482 阅读3分钟

这里梳理一下鸿蒙自定义 Toast 提示实现思路。一般在应用里一些错误信息都会用到 Toast 提示,而这些相似的提示功能不可能在需要的每一个页面里都重复写一遍,最方便的方式还是用一个全局对象进行管理,那么,这里就需要一个通用展示 Toast 提示的地方,这里可以直接创建一个子窗口,子窗口加载自定义提示内容,应用在需要提示的地方用全局对象去操作子窗口即可。

一、效果展示

2024-10-0515.19.29-ezgif.com-video-to-gif-converter.gif

二、代码实现

调用下面的几行实例代码就实现上面的提示效果,而无需为每个 page 页面进行重复的页面搭建

WSLToastShow({ content: '清理中',toastType: ToastType.ToastProgress })
setTimeout(()=>{
  WSLToastShow({ content: '清除成功',toastType: ToastType.ToastNormalNoShowDefaultTitle })
},2000)

上面说明了 Toast 是在子窗口下进行展示的,那么,第一步肯定是要创建子窗口并把它展示在主屏幕上。

1、注册 window.WindowStage

因为后面需要用到 WindowStage 这个实例对象,那么,在项目的入口文件 EntryAbility.ets 里保存一下

import { WindowManager } from '@kit.SpeechKit';

onWindowStageCreate(windowStage: window.WindowStage): void {
  // 保存当前的主窗口
  WindowManager.setWindowStage(windowStage)
}

2、创建子窗口

import { WindowManager } from '@kit.SpeechKit';

createSubWindow(subWindowName: string = 'WSLCustomSubWindow',page: string){
  WindowManager.getWindowStage().createSubWindow(subWindowName,(err,subWindow)=> {
    WindowManager.getWindowStage().getMainWindow().then((mainWindow)=>{
      let screenWidth = mainWindow.getWindowProperties().windowRect.width
      let screenHeight = mainWindow.getWindowProperties().windowRect.height
      subWindow.setUIContent(page)
      subWindow.resize(screenWidth,screenHeight)
      subWindow.setWindowTouchable(false)
      subWindow.showWindow((err)=>{
        if(!err.code){
          try {
            subWindow.setWindowBackgroundColor('#00000000')
          } catch (e) {
          }
        }
      })
    })
  }
 })
}

WindowManager.getWindowStage().createSubWindow 来创建子窗口,需要设置子窗口的名字,后面会用于销毁对应的子窗口。在创建回调方法里设置子窗口的位置、大小及加载的页面路径,subWindow.setWindowTouchable(false) 方法设置子窗口不可进行手势交互,这意味着展示过程中,用户仍然能进行其他操作,如果某些操作是要完全等待的操作,那么,可以将手势交互打开。最后,设置窗口的背景颜色为完全透明,剩下的提示效果就是在 page 页面里进行搭建了。

3、销毁子窗口

提示成功了,或者有新的提示内容,那么,就销毁之前子窗口。(注:其实不需要每次都去销毁它,可以用懒加载的方式创建子窗口,在后面需要用到的地方进行子窗口内部页面的内容展示与隐藏)这里还是用的是完全销毁操作,简单粗暴。

function WSLToastDismiss(subWindowName:string,callBack?:AsyncCallback<void>){
  try {
    window.findWindow(subWindowName).destroyWindow(callBack)
  } catch (e) {
    callBack && callBack(null)
  }
}

调用 window.findWindow(subWindowName).destroyWindow(callBack) 方法 销毁对应的名字的子窗口。

4、提示内容的传递

主窗口页面操作子窗口页面的展示内容,那么简单的方式就是用 AppStorageV2.connect 实现应用内数据共享,在打开子窗口前进行新数据的替换,等到子窗口加载 page 页面时,拿到最新的数据进行展示。

//展示新的弹窗提供内容源
const saveModel = AppStorageV2.connect(ToastModel, () => new ToastModel())!

三、总结与思考

这里主要熟悉一下,子窗口的创建、加载页面、销毁等操作,在子窗口下操作可减少每次提示需要的相同逻辑,提示的样式及操作,又完全可以自定义。对于系统的 CustomDialogController 自定义弹窗,需要传入一个 @Builder 修饰的构建方法参数,用法不复杂,但不同页面展示的时候就会导致重复代码创建,对于相同的功能反而有点啰嗦了。希望能帮助到大家[抱拳][抱拳][抱拳]