【HarmonyOS】鸿蒙多 Toast 显示工具类
作者:zhongcx
- 2024-10-11 广东
本文字数:4711 字
阅读完需:约 15 分钟
【HarmonyOS】封装可以同时显示多个 toast 的工具类
src/main/ets/common/MyPromptActionUtil.ets
import { ComponentContent, PromptAction, window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
// MyPromptInfo 类用于生成唯一的 dialogID
export class MyPromptInfo {
public dialogID: string
constructor() {
this.dialogID = this.generateRandomString(10)
}
// 生成指定长度的随机字符串
generateRandomString(length: number): string {
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
result += characters.charAt(randomIndex);
}
return result;
}
}
// MyPromptActionUtil 类用于封装弹窗操作
export class MyPromptActionUtil<T extends MyPromptInfo> {
static myDialogPromptActionUtil: MyPromptActionUtil<MyToastInfo> | undefined = undefined
public static showToast(message: string) {
if (!MyPromptActionUtil.myDialogPromptActionUtil) { //当前页面没显示toast
// getContext().eventHub.off(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID)
// MyPromptActionUtil.myDialogPromptActionUtil?.closeCustomDialog() //如果之前有的toast对话框,并且正在显示,则先关闭toast提示
window.getLastWindow(getContext()).then((windowClass) => {
const uiContext = windowClass.getUIContext()
MyPromptActionUtil.myDialogPromptActionUtil =
new MyPromptActionUtil<MyToastInfo>(uiContext, wrapBuilder(myToastView), new MyToastInfo(message))
.setModal(false)//true:存在黑色半透明蒙层,false:没有蒙层
.setSwipeBackEnabled(false)//true:侧滑允许关闭弹窗
.setMaskTapToCloseEnabled(true)//true:点击半透明蒙层可关闭弹窗【注:如果setModal(false),那么就没有蒙层,所以点击对话框外也没有响应事件,也就是这里设置了也没效果,并且事件会穿透】
.setAlignment(DialogAlignment.Center)
.onWillAppear(() => {
console.info('在对话框的打开动画开始之前调用的回调函数')
getContext().eventHub.on(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID, (data: string) => {
//监听结果
if (data == '关闭弹窗') {
MyPromptActionUtil.myDialogPromptActionUtil?.closeCustomDialog()
}
})
})
.onWillDisappear(() => {
console.info('在对话框的关闭动画开始之前调用的回调函数')
getContext().eventHub.off(MyPromptActionUtil.myDialogPromptActionUtil?.dialogID)
MyPromptActionUtil.myDialogPromptActionUtil = undefined
})
.showCustomDialog()
})
} else { //当前正在显示toast
getContext().eventHub.emit(MyPromptActionUtil.myDialogPromptActionUtil.dialogID, { msg: message })
}
}
private uiContext: UIContext;
private promptAction: PromptAction;
private contentNode: ComponentContent<T> | undefined;
private wrapBuilder: WrappedBuilder<[T]>;
private t: T;
private isModal: boolean = true;
private alignment: DialogAlignment = DialogAlignment.Center;
private isSwipeBackEnabled: boolean = true;
private isMaskTapToCloseEnabled: boolean = true;
public dialogID: string
constructor(uiContext: UIContext, wrapBuilder: WrappedBuilder<[T]>, t: T) {
this.uiContext = uiContext;
this.promptAction = uiContext.getPromptAction();
this.wrapBuilder = wrapBuilder;
this.t = t;
this.dialogID = t.dialogID
}
setSwipeBackEnabled(isSwipeBackEnabled: boolean) {
this.isSwipeBackEnabled = isSwipeBackEnabled;
return this;
}
setMaskTapToCloseEnabled(isMaskTapToCloseEnabled: boolean) {
this.isMaskTapToCloseEnabled = isMaskTapToCloseEnabled
return this;
}
setAlignment(alignment: DialogAlignment) {
this.alignment = alignment;
return this;
}
setModal(isModal: boolean) {
this.isModal = isModal;
return this;
}
onDidAppear(callback: () => void) {
this.onDidAppearCallback = callback;
return this;
}
onDidDisappear(callback: () => void) {
this.onDidDisappearCallback = callback;
return this;
}
onWillAppear(callback: () => void) {
this.onWillAppearCallback = callback;
return this;
}
onWillDisappear(callback: () => void) {
this.onWillDisappearCallback = callback;
return this;
}
private onDidAppearCallback?: () => void;
private onDidDisappearCallback?: () => void;
private onWillAppearCallback?: () => void;
private onWillDisappearCallback?: () => void;
closeCustomDialog() {
if (this.contentNode) {
this.promptAction.closeCustomDialog(this.contentNode);
}
return this;
}
// 显示自定义弹窗
showCustomDialog() {
try {
if (!this.contentNode) {
this.contentNode = new ComponentContent(this.uiContext, this.wrapBuilder, this.t);
}
this.promptAction.openCustomDialog(this.contentNode, {
// 打开自定义弹窗
alignment: this.alignment,
isModal: this.isModal,
showInSubWindow: false,
maskRect: {
x: 0,
y: 0,
width: '100%',
height: '100%'
},
onWillDismiss: (dismissDialogAction: DismissDialogAction) => { //弹窗响应
console.info("reason" + JSON.stringify(dismissDialogAction.reason))
console.log("dialog onWillDismiss")
if (dismissDialogAction.reason == 0 && this.isSwipeBackEnabled) { //手势返回时,关闭弹窗。
this.promptAction.closeCustomDialog(this.contentNode)
}
if (dismissDialogAction.reason == 1 && this.isMaskTapToCloseEnabled) {
this.promptAction.closeCustomDialog(this.contentNode)
}
},
onDidAppear: this.onDidAppearCallback ? this.onDidAppearCallback : () => {
},
onDidDisappear: this.onDidDisappearCallback ? this.onDidDisappearCallback : () => {
},
onWillAppear: this.onWillAppearCallback ? this.onWillAppearCallback : () => {
},
onWillDisappear: this.onWillDisappearCallback ? this.onWillDisappearCallback : () => {
},
});
} catch (error) { // 错误处理
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
}
return this;
}
}
class MyToastInfo extends MyPromptInfo {
public message: string = ""
constructor(message: string) {
super()
this.message = message
}
}
@Builder
function myToastView(data: MyToastInfo) {
MyToastView({ dialogID: data.dialogID, message: data.message })
}
@ObservedV2
class ToastBean {
message: string = ""
@Trace isShow: boolean = true
constructor(message: string) {
this.message = message
}
}
@Component
struct MyToastView {
@State toast_info_list: ToastBean[] = []
@Prop dialogID: string
@Prop message: string
aboutToAppear(): void {
this.toast_info_list.push(new ToastBean(this.message))
getContext().eventHub.on(this.dialogID, (data: object) => {
if (data['msg']) {
this.toast_info_list.push(new ToastBean(data['msg']))
}
})
}
build() {
Column() {
ForEach(this.toast_info_list, (item: ToastBean) => {
Text(item.message)
.fontSize('36lpx')
.fontColor(Color.White)
.backgroundColor("#B2ff0000")
.borderRadius(8)
.constraintSize({ maxWidth: '80%' })
.padding({
bottom: '28lpx',
left: '60lpx',
right: '60lpx',
top: '28lpx'
})
.margin(5)
.visibility(item.isShow ? Visibility.Visible : Visibility.None)
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
console.info('Test Text isVisible: ' + isVisible + ', currentRatio:' + currentRatio)
if (isVisible && currentRatio >= 1.0) {
setTimeout(() => {
item.isShow = false
}, 2000)
}
})
.animation({
duration: 200, onFinish: () => {
console.info('==== onFinish')
//动画结束后,判断数组是否已全部为隐藏状态,是的话证明所有toast内容都展示完成,可以释放全局弹窗了
let isAnimAll = true
for (let i = 0; i < this.toast_info_list.length; i++) {
if (this.toast_info_list[i].isShow == true) { //至少有一个正在显示
isAnimAll = false
break;
}
}
if (isAnimAll) {
console.info('已展示完全部toast,为了性能,关闭弹窗释放view')
getContext(this).eventHub.emit(this.dialogID, "关闭弹窗")
}
}
})
.transition(TransitionEffect.OPACITY.animation({ duration: 200 }))
})
}
}
}
复制代码
src/main/ets/pages/Page01.ets
import { MyPromptActionUtil } from '../common/MyPromptActionUtil'
@Entry
@Component
struct Page01 {
build() {
Column() {
Button('显示Toast').onClick(() => {
MyPromptActionUtil.showToast(`随机数:${this.getRandomInt(1, 100)}`)
})
}
.width('100%')
.height('100%')
}
getRandomInt(min: number, max: number): number {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 4
zhongcx
关注
还未添加个人签名 2024-09-27 加入
还未添加个人简介
评论