问题现象
应用/元服务如何实现一个全局可调用的弹窗?
背景知识
windowStage为窗口管理器,管理各个基本窗口单元。
通过CustomDialogController类显示自定义弹窗,需要使用@CustomDialog定义弹窗内容。调用弹窗时,需要new CustomDialogController(),并将@CustomDialog作为CustomDialogControllerOptions中的builder参数传入。
openCustomDialog用于创建并弹出dialogContent对应的自定义弹窗。
解决方案
实现一个全局可调用弹窗,可通过如下三种方式实现:
方案一:实现全局可调用弹窗推荐使用:不依赖UI组件的全局自定义弹出框 (openCustomDialog),示例请参考完整示例。
方案二:可使用子窗口方式实现全局可调用弹窗,实现方式如下:
在EntryAbility.ets中通过AppStorage获取窗口管理器用于后续获取Window实例实现子窗口的创建与销毁,代码如下:
import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
onCreate(): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
AppStorage.setOrCreate('windowStage', windowStage);
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
};
SubWindow.ets页面封装打开弹窗createMySubWindowFun方法,通过createSubWindow实现弹窗的弹出,使用setUIContent设置SubPage页面为子窗口加载的具体页面内容,通过moveWindowTo、resize等方法设置子窗口样式。封装deleteMySubWindowFun方法通过destroyWindow实现弹窗的关闭。代码如下:
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
// 获取windowStage
let windowStage = AppStorage.get('windowStage') as window.WindowStage;
let windowClass: window.Window | undefined = undefined;
export class mySubWindow {
createMySubWindowFun(subWindowName: string) {
// 创建子窗口
windowStage.createSubWindow(subWindowName, (err: BusinessError, data) => {
windowClass = data;
data.setUIContent('pages/SubPage', () => {
// 设置子窗口左上角坐标
data.moveWindowTo(150, 300);
// 设置子窗口大小
data.resize(1000, 1000);
// 展示子窗口
data.showWindow();
});
});
}
deleteMySubWindowFun() {
if (windowClass) {
windowClass.destroyWindow();
}
}
}
SubPage.ets页面用于展示子窗页面内容,代码如下:
// 子窗口显示页面
import { mySubWindow } from '../utils/SubWindow';
@Entry
@Component
struct SubPage {
mySubWindow: mySubWindow = new mySubWindow();
build() {
Column() {
Text('子窗口页面')
.fontSize(40)
.margin({ top: 30 });
Button('点击关闭')
.onClick(() => {
this.mySubWindow.deleteMySubWindowFun();
})
.margin({ top: 100 });
}
.width('100%')
.height('100%');
}
}
Index.ets页面使用方式通过引入SubWindow页面,通过调用封装的createMySubWindowFun方法实现弹窗的打开,代码如下:
import { mySubWindow } from '../utils/SubWindow';
@Entry
@Component
struct Index {
mySubWindow: mySubWindow = new mySubWindow();
build() {
RelativeContainer() {
Text('点击打开弹窗')
.id('HelloWorld')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: 'container', align: VerticalAlign.Center },
middle: { anchor: 'container', align: HorizontalAlign.Center }
})
.onClick(() => {
this.mySubWindow.createMySubWindowFun('mySubWindow');
});
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5');
}
}
运行效果图如下:
点击放大
方案三:通过自定义弹窗(CustomDialog)封装成自定义组件的方式:
封装弹窗控制方法Dialog.ets,使用@watch监听外部传入的变量变化,通过CustomDialogController控制弹窗的显示隐藏,代码如下:
import { CustomDialogView } from './CustomDialogView';
@Component
export struct Dialog {
// 监听外部传入的visible变量,visible值发生变化时触发onChange回调函数
@Watch('onChange') @Link visible: boolean;
onCancel?: () => void;
onConfirm?: () => void;
// 通过CustomDialogController的builder参数绑定弹窗组件CustomDialogView
private controller = new CustomDialogController({
builder: CustomDialogView({
visible: $visible,
onCancel: this.onCancel,
onConfirm: this.onConfirm,
}),
autoCancel: false,
alignment: DialogAlignment.Center,
});
// 当visible的值变化时触发回调
onChange(): void {
if (this.visible) {
this.controller.open();
} else {
this.controller.close();
}
}
// 二次封装的Dialog组件主要通过控制器控制弹窗,不需要任何界面
build() {
}
}
封装弹窗视图页面CustomDialogView.ets,作用于弹窗中作为展示页面,代码如下:
@CustomDialog
export struct CustomDialogView {
@Link visible: boolean;
controller: CustomDialogController;
// 弹窗交互事件参数,点击确认和取消按钮时的回调函数
onCancel?: () => void;
onConfirm?: () => void;
build() {
Column() {
Text('自定义弹窗')
.margin({ top: 20, bottom: 40 });
Button('点击关闭弹窗').onClick(() => {
// 重置弹窗显隐参数
this.visible = false;
// 关闭弹窗
this.controller.close();
});
}
.width('100%')
.height(200)
.backgroundColor(Color.White);
}
}
使用弹窗页面CustomDialog.ets,通过给引入的Dialog组件传入visible控制弹窗的弹出,代码如下:
import { Dialog } from './Dialog';
@Entry
@Component
export struct CustomDialog {
// 外部定义visible变量作为弹窗组件入参,控制弹窗显隐
@State visible: boolean = false;
build() {
Column({ space: 20 }) {
Button('点击打开弹窗')
// 点击修改visible变量后,visible的值可以被Dialog组件监听并响应
.onClick(() => this.visible = !this.visible)
.margin({ top: 40 });
// 通过双向绑定visible变量,实现外部控制弹窗
Dialog({
visible: $visible,
});
}
.width('100%');
}
}
运行效果图如下:
点击放大
总结
实现全局可调用弹窗可通过openCustomDialog、子窗口与自定义弹窗方式实现,openCustomDialog通过ComponentContent封装内容可以与UI界面解耦,调用更加灵活,可以满足开发者的封装诉求,优先推荐使用。子窗口方式需要使用页面当作弹窗内容且需要获取窗口管理器,代码复杂性较高。自定义弹窗方式与调用UI界面耦合性较高也不建议使用。
https://coub.com/view/4b7ub4
https://coub.com/view/4b7ub3
https://coub.com/view/4b7ub2
https://coub.com/view/4b7ub0
https://coub.com/view/4b7uay
https://coub.com/view/4b7uax
https://coub.com/view/4b7uav
https://coub.com/view/4b7uap
https://coub.com/view/4b7uao
https://coub.com/view/4b7ual
https://coub.com/view/4b7uad
https://coub.com/view/4b7uaa
https://coub.com/view/4b7ua7
https://coub.com/view/4b7ua5
https://coub.com/view/4b7ua2
https://coub.com/view/4b7ua1
https://coub.com/view/4b7u9z
https://coub.com/view/4b7u9y
https://coub.com/view/4b7u9x
https://coub.com/view/4b7u9p
https://coub.com/view/4b7u9k
https://coub.com/view/4b7u9j
https://coub.com/view/4b7u9i
https://coub.com/view/4b7u9g
https://coub.com/view/4b7u9d
https://coub.com/view/4b7u9a
https://coub.com/view/4b7u98
https://coub.com/view/4b7u96
https://coub.com/view/4b7u94
https://coub.com/view/4b7u92
https://coub.com/view/4b7u91
https://coub.com/view/4b7u8z
https://coub.com/view/4b7u8t
https://coub.com/view/4b7u8q
https://coub.com/view/4b7u8p
https://coub.com/view/4b7u8n
https://coub.com/view/4b7u8j
https://coub.com/view/4b7u8i
https://coub.com/view/4b7u78
https://coub.com/view/4b7u76
https://coub.com/view/4b7u72
https://coub.com/view/4b7u6v
https://coub.com/view/4b7u6t
https://coub.com/view/4b7u6r
https://coub.com/view/4b7u6o
https://coub.com/view/4b7u6m
https://coub.com/view/4b7u6l
https://coub.com/view/4b7u6j
https://coub.com/view/4b7u6h
https://coub.com/view/4b7u6f
https://coub.com/view/4b7u6d
https://coub.com/view/4b7u6a
https://coub.com/view/4b7u67
https://coub.com/view/4b7u65
https://coub.com/view/4b7u60
https://coub.com/view/4b7u5t
https://coub.com/view/4b7u5p
https://coub.com/view/4b7u5i
https://coub.com/view/4b7u4t
https://coub.com/view/4b7u4p
https://coub.com/view/4b7u4l
https://coub.com/view/4b7u46
https://coub.com/view/4b7u3v
https://coub.com/view/4b7u3u
https://coub.com/view/4b7u3t
https://coub.com/view/4b7u3r
https://coub.com/view/4b7u3o
https://coub.com/view/4b7u3l
https://coub.com/view/4b7u3k
https://coub.com/view/4b7u3h
https://coub.com/view/4b7u3a
https://coub.com/view/4b7u38
https://coub.com/view/4b7u35
https://coub.com/view/4b7u34
https://coub.com/view/4b7u33
https://coub.com/view/4b7u30
https://coub.com/view/4b7u2z
https://coub.com/view/4b7u2w
https://coub.com/view/4b7pz5
https://coub.com/view/4b7pz2
https://coub.com/view/4b7pyu
https://coub.com/view/4b7pyr
https://coub.com/view/4b7pyp
https://coub.com/view/4b7pym
https://coub.com/view/4b7pyk
https://coub.com/view/4b7pya
https://coub.com/view/4b7py6
https://coub.com/view/4b7py5
https://coub.com/view/4b7py2
https://coub.com/view/4b7pxi
https://coub.com/view/4b7px8
https://coub.com/view/4b7pxd
https://coub.com/view/4b7px4
https://coub.com/view/4b7px2
https://coub.com/view/4b7pwy
https://coub.com/view/4b7pwt
https://coub.com/view/4b7pwi
https://coub.com/view/4b7pwb
https://coub.com/view/4b7pvo
https://coub.com/view/4b7pvk
https://coub.com/view/4b7pvf
https://coub.com/view/4b7pvd
https://coub.com/view/4b7pv9
https://coub.com/view/4b7pv7
https://coub.com/view/4b7puz
https://coub.com/view/4b7puu
https://coub.com/view/4b7pur
https://coub.com/view/4b7puj
https://coub.com/view/4b7puf
https://coub.com/view/4b7puc
https://coub.com/view/4b7pu5
https://coub.com/view/4b7pu3
https://coub.com/view/4b7pty
https://coub.com/view/4b7ptw
https://coub.com/view/4b7ptu
https://coub.com/view/4b7ptt
https://coub.com/view/4b7ptr
https://coub.com/view/4b7ptp
https://coub.com/view/4b7ptn
https://coub.com/view/4b7ptm
https://coub.com/view/4b7ptk
https://coub.com/view/4b7ptj
https://coub.com/view/4b7ptf
https://coub.com/view/4b7ptd
https://coub.com/view/4b7ptb
https://coub.com/view/4b7pt9
https://coub.com/view/4b7pt6
https://coub.com/view/4b7psx
https://coub.com/view/4b7pso
https://coub.com/view/4b7psl
https://coub.com/view/4b7psh
https://coub.com/view/4b7psc
https://coub.com/view/4b7ps7
https://coub.com/view/4b7ps2
https://coub.com/view/4b7prv
https://coub.com/view/4b7prm
https://coub.com/view/4b7prj
https://coub.com/view/4b7pri
https://coub.com/view/4b7lh7
https://coub.com/view/4b7lh5
https://coub.com/view/4b7lh4
https://coub.com/view/4b7lh1
https://coub.com/view/4b7lh0
https://coub.com/view/4b7lgx
https://coub.com/view/4b7lgu
https://coub.com/view/4b7lgr
https://coub.com/view/4b7lgo
https://coub.com/view/4b7lgj
https://coub.com/view/4b7lgh
https://coub.com/view/4b7lgd
https://coub.com/view/4b7lgb
https://coub.com/view/4b7lg6
https://coub.com/view/4b7lg2
https://coub.com/view/4b7lfw
https://coub.com/view/4b7lft
https://coub.com/view/4b7lfn
https://coub.com/view/4b7lfh
https://coub.com/view/4b7lfa
https://coub.com/view/4b7lek
https://coub.com/view/4b7leh
https://coub.com/view/4b7lef
https://coub.com/view/4b7lec
https://coub.com/view/4b7leb
https://coub.com/view/4b7le7
https://coub.com/view/4b7le1
https://coub.com/view/4b7ldz
https://coub.com/view/4b7ldx
https://coub.com/view/4b7ldw
https://coub.com/view/4b7ldt
https://coub.com/view/4b7ldq
https://coub.com/view/4b7ldn
https://coub.com/view/4b7lda
https://coub.com/view/4b7ld8
https://coub.com/view/4b7ld4
https://coub.com/view/4b7lcz
https://coub.com/view/4b7lcv
https://coub.com/view/4b7lcq
https://coub.com/view/4b7lco
https://coub.com/view/4b7lcm
https://coub.com/view/4b7lcj
https://coub.com/view/4b7lcd
https://coub.com/view/4b7lc9
https://coub.com/view/4b7lc0
https://coub.com/view/4b7lbx
https://coub.com/view/4b7lbw
https://coub.com/view/4b7lbv
https://coub.com/view/4b7lbu
https://coub.com/view/4b7lbt
https://coub.com/view/4b7lbc
https://coub.com/view/4b7lb5
https://coub.com/view/4b7lax
https://coub.com/view/4b7laj
https://coub.com/view/4b7laf
https://coub.com/view/4b7lae
https://coub.com/view/4b7lab
https://coub.com/view/4b7la7
https://coub.com/view/4b7l9u
https://coub.com/view/4b7l9s
https://coub.com/view/4b7l9q
https://coub.com/view/4b7l9n
https://coub.com/view/4b7l9k
https://coub.com/view/4b7l9j
https://coub.com/view/4b7l9i
https://coub.com/view/4b7l9h
https://coub.com/view/4b7l9g
https://coub.com/view/4b7l9f
https://coub.com/view/4b7l99
https://coub.com/view/4b7l95
https://coub.com/view/4b7l93
https://coub.com/view/4b7l90
https://coub.com/view/4b7l8u
https://coub.com/view/4b7l8r
https://coub.com/view/4b7l8q
https://coub.com/view/4b7l8p
https://coub.com/view/4b7l8o
https://coub.com/view/4b7l8m
https://coub.com/view/4b7l8k
https://coub.com/view/4b7l8g
https://coub.com/view/4b7l8f
https://coub.com/view/4b7l8e
https://coub.com/view/4b7l8b
https://coub.com/view/4b7l88
https://coub.com/view/4b7l86
https://coub.com/view/4b7l84
https://coub.com/view/4b7l81
https://coub.com/view/4b7l7z
https://coub.com/view/4b7l7x
https://coub.com/view/4b7l7w
https://coub.com/view/4b7l7v
https://coub.com/view/4b7l7u
https://coub.com/view/4b7l7s
0 个评论
要回复文章请先登录或注册