HarmonyOS 鸿蒙Next求类似toast的红色错误信息提示框
HarmonyOS 鸿蒙Next求类似toast的红色错误信息提示框
现有的toast弹窗改变不了背景色,我需要一个红色的起到错误提示错误的弹窗,弹出后过几秒再消失。
还有toast一次执行显示一个,需要能够同时显示多个错误弹窗,按照出现的顺序先后消失,网页端看到过类似的功能。
关于HarmonyOS 鸿蒙Next求类似toast的红色错误信息提示框的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
我写了一个,看下是不是你要的效果。
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 = ‘’;
<span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> i = <span class="hljs-number"><span class="hljs-number">0</span></span>; i < length; i++) {
<span class="hljs-keyword"><span class="hljs-keyword">const</span></span> randomIndex = <span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.floor(<span class="hljs-built_in"><span class="hljs-built_in">Math</span></span>.random() * characters.length);
result += characters.charAt(randomIndex);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> 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: <span class="hljs-number"><span class="hljs-number">200</span></span>, onFinish: () => {
console.info(<span class="hljs-string"><span class="hljs-string">'==== onFinish'</span></span>)
<span class="hljs-comment"><span class="hljs-comment">//动画结束后,判断数组是否已全部为隐藏状态,是的话证明所有toast内容都展示完成,可以释放全局弹窗了</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> isAnimAll = <span class="hljs-literal"><span class="hljs-literal">true</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> i = <span class="hljs-number"><span class="hljs-number">0</span></span>; i < <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.toast_info_list.length; i++) {
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.toast_info_list[i].isShow == <span class="hljs-literal"><span class="hljs-literal">true</span></span>) { <span class="hljs-comment"><span class="hljs-comment">//至少有一个正在显示</span></span>
isAnimAll = <span class="hljs-literal"><span class="hljs-literal">false</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">break</span></span>;
}
}
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (isAnimAll) {
console.info(<span class="hljs-string"><span class="hljs-string">'已展示完全部toast,为了性能,关闭弹窗释放view'</span></span>)
getContext(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>).eventHub.emit(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.dialogID, <span class="hljs-string"><span class="hljs-string">"关闭弹窗"</span></span>)
}
}
})
.transition(TransitionEffect.OPACITY.animation({ duration: <span class="hljs-number"><span class="hljs-number">200</span></span> }))
})
}
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
src/main/ets/pages/Page01.ets
import { MyPromptActionUtil } from ‘…/common/MyPromptActionUtil’
@Entry
@Component
struct Page01 {
build() {
Column() {
Button(‘显示Toast’).onClick(() => {
MyPromptActionUtil.showToast(随机数:${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.getRandomInt(<span class="hljs-number"><span class="hljs-number">1</span></span>, <span class="hljs-number"><span class="hljs-number">100</span></span>)}
)
})
}
.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;
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
HarmonyOS的开发者模式提供了很多实用的工具,方便我们进行调试和优化。
牛啊大佬,我之后看看
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
AlertDialog,你看看这个能满足你的需求吗
希望HarmonyOS能继续推出更多实用的功能,满足用户的不同需求。
这个和我想要的完全不搭嘎,没有背景色,无法同时出现多个。我想要的效果是接近toast的效果
要是不嫌麻烦就@CustomDialog自定义弹窗呗
自定义的话,怎么实现一次出现多个弹窗,数量是不确定的
只看样式的话,目前看到ExceptionPrompt (异常提示)比较接近