前言
各位同学大家好,很久没有更新了,最近在研究鸿蒙next自定义弹窗这一块 之前使用了 CustomDialog 一定要注册controller 所以不能完全解耦和抽象出来, 不能完全脱离UI 所以最后选择了我们的 openCustomDialog 那么废话不多说 我们正式开始。
效果图
竖版效果
横板效果
具体实现
-
弹窗布局
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+,欢迎进行课程,项目等合作。
坚果派官网地址 :
如果需要学习更多鸿蒙的知识可以关注我B站教程
课程地址
B站课程地址:www.bilibili.com/cheese/play…
项目内容:
-
1 常用布局组件的学习
-
2 网络请求工具类封装
-
3 arkui 生命周期启动流程
-
4 日志工具类的封装
-
5 自定义组合组件的封装
-
6 路由导航跳转的使用
-
7 本地地数据的缓存 以及缓存工具类的封装
-
8 欢迎页面的实现
-
9 登录案例和自动登录效果实现
-
10 请求网络数据分页上拉加载 下拉刷新的实现
-
11 list数据懒加载实现
-
12 webview组件的使用