与昨天效果相似,区别在于,一个是新开一个窗口,一个是显示当前窗口的全局弹窗

思路:

  1. 创建一个名为ManagerFinal的类。
  2. 定义map状态用来存储弹窗组件,便于后续关闭弹窗
  3. 获取当前窗口需要用到上下文,没有就在当前环境中获取
  4. 定义showArt方法用于显示弹窗:
    1. 获取当前窗口拿到UIContext,在通过UIContext拿到全局弹窗
    2. 创建一个组件显示弹窗的内容,并把组件存到map中
    3. 打开弹窗
  5. 定义closeArt方法用于关闭弹窗:
    1. 获取当前窗口拿到UIContext,在通过UIContext拿到全局弹窗
    2. 拿到当前组件关闭弹窗,清除map中的组件

代码:

        下面有代码中api的大致意思

import { AdvertClass } from '../viewmodels'
import { ComponentContent, promptAction, window } from '@kit.ArkUI'
import { util } from '@kit.ArkTS'

// 展示弹窗的结构
@Builder
function uiBuilder(uiObj: AdvertClass) {
  // 弹窗内容...
}

export class ManagerFinal {
  context?: Context
  // 所有的弹窗都放到这个map中 通过name来标识
  private map: Map<string, ComponentContent<AdvertClass>> = new Map()
 
  async showArt(uiObj: AdvertClass) {
    // 生成一个name
    let name: string = `dialog_${util.generateRandomUUID()}`
    // 拿到当前最顶层的窗口
    const mainWin = await window.getLastWindow(this.context || getContext()) 
    let uiContext = mainWin.getUIContext() // 拿到UIContext
    let promptAction = uiContext.getPromptAction() // 拿到当前窗口的全局提示框
    uiObj.dialogName = name // 将dialog的弹窗名称传到builder中,方便再builder中关闭弹窗
    // 创建一个组件
    let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), uiObj)
    let options: promptAction.BaseDialogOptions = { // 弹窗配置对象
      alignment: DialogAlignment.Center, // 居中
      autoCancel: false // 不自动关闭
    }
    this.map.set(name, contentNode) // 将key/value写入到map中
    promptAction.openCustomDialog(contentNode, options) // 打开弹窗
  }

  async closeArt(name: string) {
    if (name) {
      const mainWin = await window.getLastWindow(this.context || getContext())
      let uiContext = mainWin.getUIContext()
      let promptAction = uiContext.getPromptAction()
      promptAction.closeCustomDialog(this.map.get(name)) // 关闭弹窗
      // 清理map
      this.map.delete(name) // 删除已经关闭的弹窗
    }
  }
}

// 暴露类
export const managerFinal = new ManagerFinal()

知识点:

1. 获取最上层的窗口window.getLastWindow

  • getLastWindow(ctx: BaseContext): Promise<Window>
  • 获取当前应用内最上层的子窗口,若无应用子窗口,则返回应用主窗口,使用Promise异步回调。

2. 获取当前窗口的上下文getUIContext

  • window实例.getUIContext(): UIContext
  • 获取UIContext实例。
  • 就是里面存储了当前窗口的很多东西,详细看官网

类型

说明

UIContext

返回UIContext实例对象。

3. 编程式创建一个组件ComponentContent

  • constructor(uiContext: UIContext, builder: WrappedBuilder<[]>)
  • 创建一个组件

uiContext

UIContext

创建对应节点时候所需要的UI上下文。

builder

WrappedBuilder<[]>

封装不带参builder函数的WrappedBuilder对象。

// 创建一个组件
// (上下文,全局builder,builder所需参数)
let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), uiObj)

4. 全局自定义弹出框promptAction

要先拿到窗口实例在拿到窗口的上下文才能通过getPromptAction()拿到全局自定义弹出框

  1. openCustomDialog(组件,弹窗配置对象) 打开弹窗
  2. closeCustomDialog(组件) 关闭弹窗
// 拿到当前最顶层的窗口
const mainWin = await window.getLastWindow(this.context || getContext())
// 拿到UIContext
let uiContext = mainWin.getUIContext()
// 拿到当前窗口的全局弹窗
let promptAction = uiContext.getPromptAction()

// 创建一个组件
let contentNode = new ComponentContent(uiContext, wrapBuilder(AdBuilder), uiObj)
// 弹窗配置对象
let options: promptAction.BaseDialogOptions = {
  alignment: DialogAlignment.Center,
  autoCancel: false
}

// 将key/value写入到map中
this.map.set(name, contentNode)

promptAction.openCustomDialog(contentNode, options) // 打开弹窗



promptAction.closeCustomDialog(this.map.get(name)) // 关闭弹窗

 效果:

广告场景        

都可灵活,结构看着写,点击关闭、倒计时关闭随便写...

  结构代码: 

// 弹窗的结构
@Builder
function AdBuilder(ad: AdvertClass) {
  Column() {
    Column({space: 30}) {
      Text('广告招租')
        .fontSize(60)
      Image($r('app.media.caixukun'))
        .width(100)
        .height(100)
    }
    .justifyContent(FlexAlign.Center)
    .width("100%")
    .height("100%")
    Row() {
      Image($r("app.media.ic_btn_close"))
        .width(14)
        .aspectRatio(1)
        .fillColor("#ccc")
    }
    .width(30)
    .aspectRatio(1)
    .justifyContent(FlexAlign.Center)
    .borderRadius(15)
    .position({ right: 20, top: 40 })
    .border({
      color: '#ff343232',
      width: 2
    })
    .margin({
      top: 40
    })
    .onClick(() => {
      if (ad.dialogName) {
        adManagerFinal.closeAd(ad.dialogName) // 关闭弹窗
      }
    })
  }
  .width(ad.isFull ? "100%" : "80%")
  .height(ad.isFull ? "100%" : "50%")
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐