可以通过使用自定义弹窗和定时器达到类似Toast的效果。

场景一:自定义弹窗实现弹窗中加入icon和文字,支持Button。

方案

  1. 使用@CustomDialog装饰器装饰自定义弹窗,在此装饰器内进行自定义内容(也就是弹框内容)、并创建构造器,与装饰器呼应相连。
  2. 使用定时器,在页面的生命周期onPageShow中设置定时任务,页面显示时打开弹窗。

核心代码

@CustomDialog
struct CustomDialogExample {
  controller?: CustomDialogController

  build() {
    Row() {
      Image($r('app.media.huawei'))
        .height(60)
        .width(60)
        .margin(20)
        .borderRadius(10)
      Text('Toast弹窗')
      Button('进入')
        .onClick(() => {
          if (this.controller != undefined) {
            this.controller.close()
          }
        })
        .margin(20)
    }
    .width('100%')
    .backgroundColor(Color.Grey)
  }
}

@Entry
@Component
struct CustomDialogUser {
  dialogController: CustomDialogController | null = new CustomDialogController({
    builder: CustomDialogExample(),
    autoCancel: true,
    alignment: DialogAlignment.CenterStart,
    offset: { dx: 10, dy: 10 },
    gridCount: 4,
    showInSubWindow: false,
    isModal: true,
    customStyle: false,
    cornerRadius: 10,
  })

  // 使用定时器,在页面的生命周期 onPageShow中设置定时任务,页面显示时打开弹窗
  onPageShow() {
    setTimeout(() => {
      if (this.dialogController != null) {
        this.dialogController.open()
      }
    }, 2000);
  }

  build() {
    Column() {
      // ...
    }
  }
}

场景二:自定义弹窗样式。

  1. 可自定义弹窗位置,5.0规格,未设置alignment弹窗默认居中显示。
  2. 可设置弹窗宽度、高度。gridCount弹窗宽度占栅格宽度的个数最大为4栅格宽度(400vp),API 12可通过width和height属性指定宽高。

    弹窗高度最大值:0.9 *(窗口高度 - 安全区域)

  3. 可设置是否有蒙层,有蒙层时可自定义蒙层颜色。
  4. 可设置弹框边框样式、边框宽度、边框颜色。
  5. 可设置弹窗背板阴影、模糊材质。

方案

  1. 使用@CustomDialog装饰器装饰自定义弹窗,在此装饰器内进行自定义内容。
  2. 创建构造器时CustomDialogController时,customStyle为true,弹窗的样式则为装饰器内自定义的弹窗内容的样式。弹窗位置,是否为模态窗口、蒙层颜色则需要在构造器内使用。

核心代码

@CustomDialog
struct CustomDialogExample02 {
  controller?: CustomDialogController

  build() {
    Row() {
      Text('为您更新一组内容')
        .fontColor(Color.White)
        .margin({ left: 5 })
    }
    .borderRadius(25)
    .width('40%')
    .height(40)
    .backgroundColor('#33FF66')
  }
}

@Entry
@Component
export struct TestSubtab {
  @State currentIndex: number = 0
  @State changeValue: string = ''
  controller: SearchController = new SearchController()
  dialogController: CustomDialogController | null = new CustomDialogController({
    builder: CustomDialogExample02(),
    autoCancel: true, // 是否允许点击遮障层退出,true表示关闭弹窗。
    alignment: DialogAlignment.TopStart, // 弹窗在竖直方向上的对齐方式。
    offset: { dx: 100, dy: 10 }, // 弹窗相对alignment所在位置的偏移量。
    showInSubWindow: false, // 弹窗显示在应用内,而非独立子窗口。
    isModal: true, // 设置弹窗是否为模态窗口,也就是是否有蒙层
    customStyle: true, // 弹窗容器样式是否自定义。
    maskColor: Color.Transparent // 自定义蒙层颜色。这里设置蒙层为全透明
  })

  onPageShow() {
    setTimeout(() => {
      if (this.dialogController != null) {
        this.dialogController.open()
      }
    }, 2000);
  }

  build() {
    Column() {
      // ....
    }
  }
}

场景三:自定义弹窗实现弹窗打开时有从底部向上弹出的效果,以及关闭时从下消失的效果。

方案

当前自定义弹窗的openAnimation和closeAnimation只能实现弹窗原地打开的相关动画设置,无法设置弹窗位置上变化的效果。为了避免弹窗原地打开关闭,这里选择通过给弹窗设置组件转场动画(transition)来实现。当然也可以根据具体想要实现的效果选择其他动画来自定义弹窗动画。

  1. 设置动画事件为500ms组件转场时插入的起点和删除的终点为屏幕以下300vp。
  2. 在删除的时候需要注意,如果弹窗直接关闭是没有转场效果的,可以先用显隐控制,删除时,设置弹窗为隐藏,此时弹出向下退出的动效生效,再设置延时关闭弹窗。

核心代码

@CustomDialog
struct CustomDialogExample01 {
  controller: CustomDialogController
  @State showFlag: Visibility = Visibility.Visible;

  build() {
    Column() {
      Row() {
        Image($r('app.media.huawei'))
          .height(60)
          .width(60)
          .margin(20)
          .borderRadius(10)
        Text('Toast弹窗')
        Button('进入')
          .onClick(() => {
            this.cancel();
          })
          .margin(20)
      }
      .width('100%')
      .backgroundColor(Color.Grey)
    }
    .width("100%")
    .height(100)
    .backgroundColor(Color.Pink)
    .visibility(this.showFlag)
    // 核心代码 设置动画事件为500ms ,设置组件转场时插入的起点和删除的终点为屏幕以下300vp
    // 弹窗显示和消失配置为相同的过渡效果(出现和消失互为逆过程)
    // 出现时从指定的透明度为0、沿y轴平移300vp,变为默认的透明度为1,透明度与旋转动画时长都为500ms
    // 消失时从默认的透明度为1、沿y轴平移300vp,变为指定的透明度为0,透明度与旋转动画时长都为500ms
    .transition(TransitionEffect.OPACITY.animation({ duration: 500 })
      .combine(TransitionEffect.translate({ y: 300 })))
  }

  // 在删除的时候需要注意,如果弹窗直接关闭是没有转场效果的,可以先用显隐控制,
  // 设置弹窗为隐藏,此时弹出向下退出的动效生效,再设置延时关闭弹窗。
  cancel() {
    this.showFlag = Visibility.Hidden
    setTimeout(() => {
      this.controller.close()
    }, 500)
  }
}

HarmonyOS码上奇行
7k 声望2.8k 粉丝