HarmonyOS应用通知与弹窗:从Toast到自定义Dialog
通知和弹窗是应用与用户交互的重要方式,HarmonyOS提供了丰富的通知机制和弹窗组件。本文将全面讲解从简单的Toast提示到复杂的自定义Dialog的实现,帮助您构建良好的用户交互体验。
一、Toast提示消息
1.1 Toast基础概念
Toast是一种轻量级的消息提示机制,它会在屏幕底部短暂显示后自动消失,不会打断用户操作。
特性分析:
- 非阻塞式:不中断用户当前操作
- 自动消失:显示2-3秒后自动关闭
- 位置固定:通常显示在屏幕底部
- 样式简单:文字提示,不支持复杂交互
1.2 基础Toast使用
import prompt from '@ohos.prompt'
@Component
struct ToastExamples {
build() {
Column({ space: 15 }) {
Text('Toast提示示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Button('基础Toast')
.onClick(() => {
prompt.showToast({
message: '这是一个基础Toast提示',
duration: 2000, // 显示时长(毫秒)
bottom: 100 // 距离底部距离
})
})
Button('长文本Toast')
.onClick(() => {
prompt.showToast({
message: '这是一个比较长的Toast提示消息,会自动换行显示',
duration: 3000
})
})
Button('带图标Toast')
.onClick(() => {
prompt.showToast({
message: '操作成功',
duration: 2000
})
})
}
.width('100%')
.padding(20)
}
}
1.3 Toast高级应用
class ToastManager {
// 显示成功提示
static showSuccess(message: string): void {
prompt.showToast({
message: message,
duration: 2000,
bottom: 150
})
}
// 显示错误提示
static showError(message: string): void {
prompt.showToast({
message: message,
duration: 2500,
bottom: 150
})
}
// 显示警告提示
static showWarning(message: string): void {
prompt.showToast({
message: message,
duration: 2000,
bottom: 150
})
}
// 显示加载中提示
static showLoading(message: string = '加载中...'): void {
prompt.showToast({
message: message,
duration: 0, // 0表示不自动关闭
bottom: 150
})
}
// 关闭Toast
static hideToast(): void {
prompt.hideToast()
}
}
// 使用示例
ToastManager.showSuccess('数据保存成功')
ToastManager.showError('网络连接失败')
二、ActionSheet操作菜单
2.1 ActionSheet基础使用
ActionSheet是从屏幕底部滑出的操作菜单,用于提供多个相关操作选项。
@Component
struct ActionSheetExamples {
build() {
Column({ space: 15 }) {
Text('ActionSheet示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Button('显示操作菜单')
.onClick(() => {
this.showImageActionSheet()
})
}
.width('100%')
.padding(20)
}
// 图片操作菜单
private showImageActionSheet(): void {
const buttons = [
{
text: '拍照',
color: '#007DFF'
},
{
text: '从相册选择',
color: '#007DFF'
},
{
text: '查看大图',
color: '#007DFF'
}
]
prompt.showActionMenu({
title: '图片操作',
buttons: buttons,
success: (index: number) => {
this.handleImageAction(index)
},
cancel: () => {
console.log('用户取消了操作')
}
})
}
private handleImageAction(index: number): void {
switch (index) {
case 0:
this.takePhoto()
break
case 1:
this.pickFromGallery()
break
case 2:
this.viewLargeImage()
break
}
}
private takePhoto(): void {
ToastManager.showSuccess('打开相机')
}
private pickFromGallery(): void {
ToastManager.showSuccess('打开相册')
}
private viewLargeImage(): void {
ToastManager.showSuccess('查看大图')
}
}
2.2 带图标的ActionSheet
private showAdvancedActionSheet(): void {
const buttons = [
{
text: '微信分享',
color: '#07C160',
icon: $r('app.media.wechat_icon')
},
{
text: '朋友圈分享',
color: '#07C160',
icon: $r('app.media.moment_icon')
},
{
text: 'QQ分享',
color: '#12B7F5',
icon: $r('app.media.qq_icon')
},
{
text: '微博分享',
color: '#E6162D',
icon: $r('app.media.weibo_icon')
}
]
prompt.showActionMenu({
title: '分享到',
buttons: buttons,
success: (index: number) => {
this.handleShareAction(index)
}
})
}
三、Dialog对话框
3.1 系统标准Dialog
HarmonyOS提供了多种标准对话框,适用于常见的交互场景。
@Component
struct SystemDialogExamples {
@State userName: string = ''
build() {
Column({ space: 15 }) {
Text('系统对话框示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Button('确认对话框')
.onClick(() => {
this.showConfirmDialog()
})
Button('输入对话框')
.onClick(() => {
this.showInputDialog()
})
Button('单选对话框')
.onClick(() => {
this.showSingleChoiceDialog()
})
Button('多选对话框')
.onClick(() => {
this.showMultiChoiceDialog()
})
Text(`用户名: ${this.userName}`)
.fontSize(14)
.margin({ top: 20 })
}
.width('100%')
.padding(20)
}
// 确认对话框
private showConfirmDialog(): void {
prompt.showDialog({
title: '确认删除',
message: '您确定要删除这条记录吗?此操作不可撤销。',
buttons: [
{
text: '取消',
color: '#666666'
},
{
text: '确定删除',
color: '#FF3B30'
}
],
success: (index: number) => {
if (index === 1) {
this.deleteRecord()
}
}
})
}
// 输入对话框
private showInputDialog(): void {
prompt.showDialog({
title: '输入用户名',
message: '请输入您的用户名:',
autoClose: false, // 不自动关闭
editors: [
{
type: prompt.InputType.TEXT,
text: this.userName,
placeholder: '请输入用户名'
}
],
buttons: [
{
text: '取消'
},
{
text: '确定'
}
],
success: (index: number, value: string) => {
if (index === 1) {
this.userName = value
ToastManager.showSuccess(`用户名设置为: ${value}`)
}
}
})
}
// 单选对话框
private showSingleChoiceDialog(): void {
const options = ['选项一', '选项二', '选项三']
prompt.showDialog({
title: '单选选择',
message: '请选择一个选项:',
editors: [
{
type: prompt.InputType.RADIO,
options: options,
selected: 0 // 默认选中第一个
}
],
buttons: [
{
text: '取消'
},
{
text: '确定'
}
],
success: (index: number, value: number) => {
if (index === 1) {
ToastManager.showSuccess(`选择了: ${options[value]}`)
}
}
})
}
// 多选对话框
private showMultiChoiceDialog(): void {
const options = ['音乐', '体育', '读书', '旅游', '游戏']
prompt.showDialog({
title: '兴趣爱好',
message: '请选择您的兴趣爱好:',
editors: [
{
type: prompt.InputType.CHECKBOX,
options: options,
selected: [0, 2] // 默认选中项
}
],
buttons: [
{
text: '取消'
},
{
text: '确定'
}
],
success: (index: number, value: number[]) => {
if (index === 1) {
const selected = value.map(i => options[i]).join(', ')
ToastManager.showSuccess(`选择了: ${selected}`)
}
}
})
}
private deleteRecord(): void {
ToastManager.showSuccess('记录删除成功')
}
}
四、自定义Dialog实现
4.1 基础自定义Dialog
当系统对话框无法满足需求时,可以创建完全自定义的Dialog。
@Component
struct CustomDialogExample {
@State isDialogVisible: boolean = false
@State dialogType: string = 'info'
build() {
Column({ space: 20 }) {
Text('自定义Dialog示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Row({ space: 15 }) {
Button('信息对话框')
.onClick(() => {
this.dialogType = 'info'
this.isDialogVisible = true
})
Button('警告对话框')
.onClick(() => {
this.dialogType = 'warning'
this.isDialogVisible = true
})
Button('输入对话框')
.onClick(() => {
this.dialogType = 'input'
this.isDialogVisible = true
})
}
// 自定义Dialog
if (this.isDialogVisible) {
this.buildCustomDialog()
}
}
.width('100%')
.padding(20)
}
@Builder
buildCustomDialog() {
// 半透明背景层
Stack({ alignContent: Alignment.Center }) {
// 背景遮罩
Rectangle()
.width('100%')
.height('100%')
.backgroundColor('#000000')
.opacity(0.5)
.onClick(() => {
this.isDialogVisible = false
})
// 对话框内容
Column({ space: 0 }) {
this.buildDialogHeader()
this.buildDialogContent()
this.buildDialogActions()
}
.width('80%')
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 24, color: '#40000000' })
}
.width('100%')
.height('100%')
.position({ x: 0, y: 0 })
}
@Builder
buildDialogHeader() {
let title = ''
let icon = $r('app.media.info_icon')
let bgColor = '#007DFF'
switch (this.dialogType) {
case 'warning':
title = '警告'
icon = $r('app.media.warning_icon')
bgColor = '#FF9500'
break
case 'input':
title = '输入信息'
icon = $r('app.media.edit_icon')
bgColor = '#34C759'
break
default:
title = '信息'
}
Row({ space: 10 }) {
Image(icon)
.width(20)
.height(20)
Text(title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
}
.width('100%')
.padding(20)
.backgroundColor(bgColor)
.borderRadius({ topLeft: 12, topRight: 12 })
}
@Builder
buildDialogContent() {
Column({ space: 15 }) {
if (this.dialogType === 'input') {
this.buildInputContent()
} else {
this.buildMessageContent()
}
}
.width('100%')
.padding(20)
}
@Builder
buildInputContent() {
Column({ space: 10 }) {
Text('请输入您的信息:')
.fontSize(14)
.fontColor('#666')
TextInput({ placeholder: '请输入内容' })
.width('100%')
.height(40)
.backgroundColor('#F5F5F5')
.padding(10)
.borderRadius(6)
}
}
@Builder
buildMessageContent() {
Text(this.dialogType === 'warning' ?
'这是一个警告消息,请注意相关操作的风险。' :
'这是一个普通的信息提示消息。'
)
.fontSize(14)
.fontColor('#333')
.textAlign(TextAlign.Center)
}
@Builder
buildDialogActions() {
Row({ space: 10 }) {
if (this.dialogType === 'warning') {
Button('取消')
.layoutWeight(1)
.backgroundColor('#666666')
.fontColor(Color.White)
.onClick(() => {
this.isDialogVisible = false
})
}
Button(this.dialogType === 'input' ? '确定' : '我知道了')
.layoutWeight(1)
.backgroundColor('#007DFF')
.fontColor(Color.White)
.onClick(() => {
this.handleDialogConfirm()
})
}
.width('100%')
.padding(20)
}
private handleDialogConfirm(): void {
ToastManager.showSuccess('对话框操作确认')
this.isDialogVisible = false
}
}
4.2 高级自定义Dialog组件
创建可复用的自定义Dialog组件:
@Component
struct CustomAlertDialog {
@Prop title: string = ''
@Prop message: string = ''
@Prop type: 'info' | 'warning' | 'error' | 'success' = 'info'
@Prop visible: boolean = false
@Prop onClose: () => void = () => {}
@Prop onConfirm: () => void = () => {}
build() {
if (this.visible) {
Stack({ alignContent: Alignment.Center }) {
// 遮罩层
Rectangle()
.width('100%')
.height('100%')
.backgroundColor('#000000')
.opacity(0.5)
.onClick(() => {
this.onClose()
})
// 对话框主体
Column({ space: 0 }) {
// 标题栏
this.buildHeader()
// 内容区域
Column({ space: 15 }) {
Text(this.message)
.fontSize(14)
.fontColor('#333')
.textAlign(TextAlign.Center)
}
.width('100%')
.padding(20)
// 操作按钮
Row({ space: 10 }) {
Button('取消')
.layoutWeight(1)
.backgroundColor('#666666')
.fontColor(Color.White)
.onClick(() => {
this.onClose()
})
Button('确定')
.layoutWeight(1)
.backgroundColor(this.getConfirmButtonColor())
.fontColor(Color.White)
.onClick(() => {
this.onConfirm()
})
}
.width('100%')
.padding(20)
}
.width('80%')
.backgroundColor(Color.White)
.borderRadius(12)
}
.width('100%')
.height('100%')
.position({ x: 0, y: 0 })
}
}
@Builder
buildHeader() {
let bgColor = '#007DFF'
let icon = $r('app.media.info_icon')
switch (this.type) {
case 'warning':
bgColor = '#FF9500'
icon = $r('app.media.warning_icon')
break
case 'error':
bgColor = '#FF3B30'
icon = $r('app.media.error_icon')
break
case 'success':
bgColor = '#34C759'
icon = $r('app.media.success_icon')
break
}
Row({ space: 10 }) {
Image(icon)
.width(20)
.height(20)
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.layoutWeight(1)
}
.width('100%')
.padding(20)
.backgroundColor(bgColor)
.borderRadius({ topLeft: 12, topRight: 12 })
}
private getConfirmButtonColor(): string {
switch (this.type) {
case 'warning': return '#FF9500'
case 'error': return '#FF3B30'
case 'success': return '#34C759'
default: return '#007DFF'
}
}
}
// 使用示例
@Component
struct CustomDialogUsage {
@State isDialogVisible: boolean = false
build() {
Column({ space: 15 }) {
Button('显示自定义对话框')
.onClick(() => {
this.isDialogVisible = true
})
CustomAlertDialog({
title: '操作确认',
message: '您确定要执行此操作吗?',
type: 'warning',
visible: this.isDialogVisible,
onClose: () => {
this.isDialogVisible = false
ToastManager.showSuccess('用户取消了操作')
},
onConfirm: () => {
this.isDialogVisible = false
ToastManager.showSuccess('操作已确认')
}
})
}
}
}
五、通知系统集成
5.1 系统通知基础
import notification from '@ohos.notification'
@Component
struct NotificationExamples {
build() {
Column({ space: 15 }) {
Text('系统通知示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Button('发送普通通知')
.onClick(() => {
this.sendBasicNotification()
})
Button('发送重要通知')
.onClick(() => {
this.sendImportantNotification()
})
Button('发送进度通知')
.onClick(() => {
this.sendProgressNotification()
})
Button('取消所有通知')
.onClick(() => {
this.cancelAllNotifications()
})
}
.width('100%')
.padding(20)
}
// 发送基础通知
private async sendBasicNotification(): Promise<void> {
try {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '新消息通知',
text: '您有一条新的消息,请及时查看。',
additionalText: '刚刚'
}
},
id: 1,
slotType: notification.SlotType.SOCIAL_COMMUNICATION
}
await notification.publish(request)
ToastManager.showSuccess('通知发送成功')
} catch (error) {
console.error('发送通知失败:', error)
ToastManager.showError('通知发送失败')
}
}
// 发送重要通知
private async sendImportantNotification(): Promise<void> {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '重要提醒',
text: '系统即将进行维护,请保存好您的工作。',
additionalText: '重要'
}
},
deliveryTime: new Date().getTime(), // 立即发送
id: 2,
slotType: notification.SlotType.SERVICE_REMINDER,
// 设置通知重要性
notificationFlags: {
sound: true,
vibration: true
}
}
await notification.publish(request)
}
// 发送进度通知
private async sendProgressNotification(): Promise<void> {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_PROGRESS,
progress: {
title: '文件下载',
text: '正在下载文件...',
progressValue: 50, // 50%进度
progressMaxValue: 100
}
},
id: 3,
slotType: notification.SlotType.OTHER
}
await notification.publish(request)
}
// 取消所有通知
private async cancelAllNotifications(): Promise<void> {
await notification.cancelAll()
ToastManager.showSuccess('所有通知已取消')
}
}
六、最佳实践与性能优化
6.1 通知管理策略
class NotificationManager {
private static notificationId: number = 1000
// 发送消息通知
static async sendMessageNotification(sender: string, message: string): Promise<void> {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: `新消息来自 ${sender}`,
text: message,
additionalText: '消息'
}
},
id: this.notificationId++,
slotType: notification.SlotType.SOCIAL_COMMUNICATION
}
await notification.publish(request)
}
// 发送系统通知
static async sendSystemNotification(title: string, content: string): Promise<void> {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: title,
text: content,
additionalText: '系统'
}
},
id: this.notificationId++,
slotType: notification.SlotType.SERVICE_REMINDER
}
await notification.publish(request)
}
// 更新进度通知
static async updateProgressNotification(id: number, progress: number, text: string): Promise<void> {
const request: notification.NotificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_PROGRESS,
progress: {
title: '下载进度',
text: text,
progressValue: progress,
progressMaxValue: 100
}
},
id: id
}
await notification.publish(request)
}
}
6.2 Dialog性能优化
@Component
struct OptimizedDialog {
@State isVisible: boolean = false
// 使用aboutToAppear进行初始化
aboutToAppear() {
console.log('Dialog组件初始化')
}
// 使用aboutToDisappear进行清理
aboutToDisappear() {
console.log('Dialog组件销毁')
}
build() {
if (this.isVisible) {
// 复杂的Dialog内容...
}
}
// 显示Dialog(带动画)
showWithAnimation() {
this.isVisible = true
// 可以添加显示动画
}
// 隐藏Dialog(带动画)
hideWithAnimation() {
// 先执行隐藏动画
setTimeout(() => {
this.isVisible = false
}, 300)
}
}
总结
通过本文的深入学习,您应该掌握了HarmonyOS通知与弹窗的完整知识体系:
- Toast提示:轻量级消息提示,不中断用户操作
- ActionSheet:底部操作菜单,提供多个相关选项
- 系统Dialog:标准对话框,支持确认、输入、选择等场景
- 自定义Dialog:完全自定义的弹窗,满足特殊UI需求
- 系统通知:状态栏通知,支持多种内容和优先级
- 最佳实践:性能优化和用户体验考虑
合理运用这些交互组件可以显著提升应用的用户体验和易用性。
需要参加鸿蒙认证的请点击 鸿蒙认证链接

浙公网安备 33010602011771号