鸿蒙next openCustomDialog 实现不依赖UI的自定义弹窗

742 阅读4分钟

前言

各位同学大家好,很久没有更新了,最近在研究鸿蒙next自定义弹窗这一块 之前使用了 CustomDialog 一定要注册controller 所以不能完全解耦和抽象出来, 不能完全脱离UI 所以最后选择了我们的 openCustomDialog 那么废话不多说 我们正式开始。

效果图

竖版效果

image.png

横板效果

image.png

具体实现

  • 弹窗布局

  build() {
    Column(){
      Text("隐私协议弹窗")
        .width('100%')
        .textAlign(TextAlign.Center)
        .height(44)
        .maxLines(1)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
        .fontColor(this.param.titleFontColor)
        .fontSize(this.param.titleFontSize)
        .padding({
          left: 30,
          right: 30
        })
      Text("请查看隐私具体内容再勾选")
        .fontColor(this.param.contentFontColor)
        .fontSize(this.param.contentFontSize)
        .padding({
          left:30,
          right:30,
          bottom:20,
          top:20
        })
      Row() {
        Checkbox()
          .shape(CheckBoxShape.ROUNDED_SQUARE)
          .select(this.checkState)
          .selectedColor($r('app.color.color_f39800'))
          .width(20)
          .height(20)
          .margin({
            right: 5
          })
          .onChange((check:boolean)=>{
            this.checkState=check;
          })
        Text("请同意隐私协议并勾选")
          .fontSize(12)
          .fontColor($r('app.color.color_999999'))
      }.width('100%')
      .padding({
        left: 30,
        right: 30,
        bottom: 20
      })
      Line()
        .width('100%')
        .height(1)
        .backgroundColor($r('app.color.color_EBEBEB'))
      Row(){
        Text("取消")
          .fontColor(this.param.cancelFontColor)
          .fontSize(this.param.clickTextFontSize)
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .onClick(() => {
            MyDialogUtils.hide();
            if (this.param.cancelClickEvent) {
              this.param.cancelClickEvent();
            }
          })
        Line()
          .width(1)
          .height('100%')
          .backgroundColor($r('app.color.color_EBEBEB'))


        Text("确认")
          .fontColor(this.param.cancelFontColor)
          .fontSize(this.param.clickTextFontSize)
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .onClick(()=>{
            //MyDialogUtils.hide();

            if(this.param.sureClickEvent){
              this.param.sureClickEvent();
            }
          })
      }.width('100%')
      .height(45)
    }.width(this.param.flag?'80%':'40%').backgroundColor($r('app.color.start_window_background'))
    .borderRadius(4)
  }

}

构建 MyDialogParams 对象和 myDialogBuilder 方法

export class MyDialogParams {
  cancelText:string|Resource=$r('app.string.cancel');
  sureText:string|Resource=$r('app.string.sure');
  clickTextFontSize:number|Resource=16;
  cancelFontColor:Resource=$r('app.color.color_565656');
  sureFontColor:Resource=$r('app.color.color_565656');
  hasTitle:boolean=true;
  titleFontSize:Resource|number=18;
  titleFontColor:Resource=$r('app.color.color_212121');
  titleText:string|Resource=$r('app.string.myDialogWarmTip');
  hasCancelButton:boolean=true;
  contentText:Resource|string="";
  contentFontColor:Resource=$r('app.color.color_212121');
  contentFontSize:Resource|number=14;
  sureClickEvent?:Function;
  cancelClickEvent?:Function;
  flag?:boolean;

}
@Builder
export function myDialogBuilder(params:MyDialogParams){
  MyDialogView({
    param:params
  })
}

显示弹窗

import { ComponentContent, PromptAction, window } from "@kit.ArkUI";
import { myDialogBuilder, MyDialogParams } from "./MyDialogView";

class MyDialogUtils{
  private static myDialog:ComponentContent<MyDialogParams> | null = null
  private static promptAction:PromptAction
  show(params:MyDialogParams){
    window.getLastWindow(getContext()).then((windowClass)=>{
      const uiContext = windowClass.getUIContext()
      MyDialogUtils.myDialog= new ComponentContent(uiContext, wrapBuilder(myDialogBuilder),params);
      MyDialogUtils.promptAction = uiContext.getPromptAction()
      MyDialogUtils.promptAction.openCustomDialog(MyDialogUtils.myDialog,
        {
          alignment:DialogAlignment.Center,// 显示具体位置
          isModal:true, //允许用户单击遮罩层退出。 
          autoCancel:false,  
          keyboardAvoidMode:KeyboardAvoidMode.NONE // 设置弹窗里面有输入框的情况调用键盘不会挤压布局
        }
      )
    })
  }
  hide(){
    MyDialogUtils.promptAction.closeCustomDialog(MyDialogUtils.myDialog);
  }
}
let  myDialogUtils=new MyDialogUtils();
export default myDialogUtils as MyDialogUtils;

我们这里通过 在window.getLastWindow 接口回调里面 去调用我们 openCustomDialog 我们的弹窗的显示 然后再调用 hide方法时候去关闭我们的弹窗

封装成单例去让外面调用

  • 我们这里需要做个横竖屏的判断

我们获取屏幕宽高去比较大小来判断横竖屏 从而设置设置我们的flag 从来显示我们的弹窗的宽度大小,因为我们在 写我我们的弹窗的布局的时候是根据这个 params.flag三目运算来设置我们弹窗的宽高的

try {
  let width = 0
  let height = 0
  let displayClass = display.getDefaultDisplaySync();
  width = displayClass.width
  height = displayClass.height
  if(width<height){
    params.flag=true;
  }else{
    params.flag=false;
  }
} catch (error) {
  console.error('Error while centering the window:', error);
  params.flag=true;
}
  • 完整代码

import MyDialogUtils from "./MyDialogUtils";
import { MyDialogParams } from "./MyDialogView";
import { display } from '@kit.ArkUI';
let displayClass: display.Display | null = null;

export  class DialogManger {
 public static instance: DialogManger | null = null

 public static getInstance() {
   if (!DialogManger.instance) {
     DialogManger.instance = new DialogManger()
   }
   return DialogManger.instance
 }

 // 设置方法为私有
 private constructor() {

 }


 /***
  *
  * 弹窗显示
  */

 public  show(){
   let params   = new MyDialogParams();
   try {
     let width = 0
     let height = 0
     let displayClass = display.getDefaultDisplaySync();
     width = displayClass.width
     height = displayClass.height
     if(width<height){
       params.flag=true;
     }else{
       params.flag=false;
     }
   } catch (error) {
     console.error('Error while centering the window:', error);
     params.flag=true;
   }
   MyDialogUtils.show(params);
 }


 /**
  *
  * 弹窗隐藏
  */

 public  hide(){
   MyDialogUtils.hide();
 }
}

最后总结

鸿蒙next 里面提供很多丰富的组件 例如 CustomDialog 还有子窗口等等, 但是最后还是选择了这个 openCustomDialog来做我们自定义弹窗一个组件的选型,同学们拿到代码之后可以自己封装一些基类base 统一设置我们的宽高比例还有我们的横竖屏设置 这样我们就不用重复写了,今天的文章就讲到这里有兴趣的同学可以继续研究 如果你觉得文章还不错麻烦给我三连 关注点赞和转发 如果了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢

团队介绍

团队介绍:坚果派由坚果等人创建,团队由12位华为HDE以及若干热爱鸿蒙的开发者和其他领域的三十余位万粉博主运营。专注于分享 HarmonyOS/OpenHarmony,ArkUI-X,元服务,仓颉,团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙 原生应用,三方库60+,欢迎进行课程,项目等合作。

坚果派官网地址 :

www.nutpi.net/

如果需要学习更多鸿蒙的知识可以关注我B站教程

课程地址

B站课程地址:www.bilibili.com/cheese/play…

项目内容:

  • 1 常用布局组件的学习

  • 2 网络请求工具类封装

  • 3 arkui 生命周期启动流程

  • 4 日志工具类的封装

  • 5 自定义组合组件的封装

  • 6 路由导航跳转的使用

  • 7 本地地数据的缓存 以及缓存工具类的封装

  • 8 欢迎页面的实现

  • 9 登录案例和自动登录效果实现

  • 10 请求网络数据分页上拉加载 下拉刷新的实现

  • 11 list数据懒加载实现

  • 12 webview组件的使用