Dialog對話框組件基礎實現

文章簡介

在HarmonyOS應用開發中,Dialog對話框組件是實現用户交互的重要工具。本文將全面介紹Dialog組件的使用方法,從基礎實現到高級應用,幫助開發者快速掌握這一核心組件的使用技巧。

官方參考資料:

  • HarmonyOS開發者文檔
  • Dialog組件API參考

一、Dialog組件概述

1.1 什麼是Dialog組件

Dialog對話框是HarmonyOS應用中常用的模態窗口組件,主要用於:

  • 顯示重要信息或警告
  • 確認用户操作
  • 收集用户輸入
  • 展示進度或狀態

1.2 Dialog組件特點

  • 模態特性:Dialog顯示時會阻止用户與其他界面元素交互
  • 靈活配置:支持自定義內容、按鈕、樣式等
  • 動畫效果:內置平滑的顯示/隱藏動畫
  • 響應式設計:自動適配不同屏幕尺寸

二、基礎Dialog實現

2.1 最簡單的AlertDialog

import { AlertDialog } from '@ohos.arkui.advanced';

@Entry
@Component
struct BasicDialogExample {
  @State isShowDialog: boolean = false;

  build() {
    Column() {
      Button('顯示基礎對話框')
        .onClick(() => {
          this.isShowDialog = true;
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    
    // Dialog組件
    if (this.isShowDialog) {
      AlertDialog(
        {
          message: '這是一個基礎提示對話框',
          confirm: {
            value: '確定',
            action: () => {
              this.isShowDialog = false;
              console.log('用户點擊了確定按鈕');
            }
          }
        }
      )
    }
  }
}

2.2 帶取消按鈕的Dialog

@Component
struct ConfirmDialogExample {
  @State isShowDialog: boolean = false;

  build() {
    Column() {
      Button('顯示確認對話框')
        .onClick(() => {
          this.isShowDialog = true;
        })
    }
    .padding(20)

    if (this.isShowDialog) {
      AlertDialog(
        {
          title: '操作確認',
          message: '您確定要執行此操作嗎?',
          primaryButton: {
            value: '取消',
            action: () => {
              this.isShowDialog = false;
              console.log('用户取消了操作');
            }
          },
          secondaryButton: {
            value: '確定',
            action: () => {
              this.isShowDialog = false;
              console.log('用户確認了操作');
            }
          }
        }
      )
    }
  }
}

三、Dialog組件核心屬性詳解

3.1 主要配置屬性

屬性名

類型

必填

描述

默認值

title

string | Resource


對話框標題


message

string | Resource


對話框消息內容


autoCancel

boolean


點擊外部是否自動關閉

true

alignment

DialogAlignment


對話框對齊方式

DialogAlignment.Default

offset

Position


對話框偏移量

{x: 0, y: 0}

3.2 按鈕配置屬性

按鈕類型

配置對象

適用場景

confirm

{value, action, fontColor}

單按鈕確認場景

primaryButton

{value, action, fontColor}

主要操作按鈕

secondaryButton

{value, action, fontColor}

次要操作按鈕

3.3 完整屬性示例

@Component
struct FullFeatureDialog {
  @State isShowDialog: boolean = false;

  build() {
    Column() {
      Button('顯示完整功能對話框')
        .onClick(() => {
          this.isShowDialog = true;
        })
    }

    if (this.isShowDialog) {
      AlertDialog(
        {
          title: '完整功能對話框',
          message: '這是一個包含所有主要屬性的對話框示例',
          autoCancel: false, // 禁止點擊外部關閉
          alignment: DialogAlignment.Center, // 居中顯示
          primaryButton: {
            value: '取消',
            fontColor: '#FF0000',
            action: () => {
              this.isShowDialog = false;
              console.log('取消操作');
            }
          },
          secondaryButton: {
            value: '確認',
            fontColor: '#007DFF',
            action: () => {
              this.isShowDialog = false;
              console.log('確認操作');
            }
          }
        }
      )
      .onWillDismiss(() => {
        console.log('對話框即將關閉');
      })
      .onDidDismiss(() => {
        console.log('對話框已關閉');
      })
    }
  }
}

四、自定義Dialog實現

4.1 使用CustomDialog創建自定義對話框

@CustomDialog
struct MyCustomDialog {
  @State dialogController: CustomDialogController | null = null;
  @Link inputText: string;

  build() {
    Column() {
      Text('自定義對話框')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20 })

      TextInput({ placeholder: '請輸入內容' })
        .width('90%')
        .height(40)
        .onChange((value: string) => {
          this.inputText = value;
        })

      Row() {
        Button('取消')
          .backgroundColor('#F2F2F2')
          .fontColor('#000000')
          .onClick(() => {
            if (this.dialogController) {
              this.dialogController.close();
            }
          })

        Button('確定')
          .backgroundColor('#007DFF')
          .fontColor('#FFFFFF')
          .margin({ left: 20 })
          .onClick(() => {
            if (this.dialogController) {
              this.dialogController.close();
            }
            console.log('輸入的內容:', this.inputText);
          })
      }
      .justifyContent(FlexAlign.End)
      .margin({ top: 30, bottom: 20 })
      .width('90%')
    }
    .width('80%')
    .backgroundColor('#FFFFFF')
    .borderRadius(16)
  }
}

@Entry
@Component
struct CustomDialogExample {
  @State isShowCustomDialog: boolean = false;
  @State inputValue: string = '';
  dialogController: CustomDialogController = new CustomDialogController({
    builder: MyCustomDialog({
      inputText: $inputValue,
      dialogController: this.dialogController
    }),
    cancel: () => {
      console.log('自定義對話框被取消');
    },
    autoCancel: true
  });

  build() {
    Column() {
      Button('顯示自定義對話框')
        .onClick(() => {
          this.dialogController.open();
        })
      
      Text('輸入的內容: ' + this.inputValue)
        .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

4.2 自定義Dialog的高級用法

@CustomDialog
struct AdvancedCustomDialog {
  controller: CustomDialogController;
  @State selectedOption: number = 0;
  private options: string[] = ['選項一', '選項二', '選項三'];

  aboutToAppear() {
    console.log('自定義對話框即將顯示');
  }

  aboutToDisappear() {
    console.log('自定義對話框即將關閉');
  }

  build() {
    Column() {
      Text('高級自定義對話框')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 })

      ForEach(this.options, (item: string, index?: number) => {
        Row() {
          Text(item)
            .fontSize(18)
          if (this.selectedOption === index) {
            Image($r('app.media.ic_radio_selected'))
              .width(20)
              .height(20)
              .margin({ left: 10 })
          } else {
            Image($r('app.media.ic_radio_unselected'))
              .width(20)
              .height(20)
              .margin({ left: 10 })
          }
        }
        .width('100%')
        .padding(15)
        .backgroundColor(this.selectedOption === index ? '#E6F2FF' : '#FFFFFF')
        .onClick(() => {
          this.selectedOption = index!;
        })
      })

      Row() {
        Button('取消')
          .layoutWeight(1)
          .onClick(() => {
            this.controller.close();
          })

        Button('確認選擇')
          .layoutWeight(1)
          .backgroundColor('#007DFF')
          .fontColor('#FFFFFF')
          .margin({ left: 10 })
          .onClick(() => {
            this.controller.close();
            console.log('用户選擇了:', this.options[this.selectedOption]);
          })
      }
      .margin({ top: 20, bottom: 20 })
      .width('90%')
    }
    .width('85%')
    .backgroundColor('#FFFFFF')
    .borderRadius(20)
    .shadow({ radius: 20, color: '#33000000', offsetX: 0, offsetY: 5 })
  }
}

五、Dialog生命週期和事件處理

5.1 生命週期方法

@Component
struct DialogLifecycleExample {
  @State isShowDialog: boolean = false;

  build() {
    Column() {
      Button('顯示帶生命週期的對話框')
        .onClick(() => {
          this.isShowDialog = true;
        })
    }

    if (this.isShowDialog) {
      AlertDialog(
        {
          title: '生命週期示例',
          message: '觀察控制枱輸出的生命週期日誌',
          primaryButton: {
            value: '取消',
            action: () => {
              this.isShowDialog = false;
            }
          },
          secondaryButton: {
            value: '確定',
            action: () => {
              this.isShowDialog = false;
            }
          }
        }
      )
      .onAppear(() => {
        console.log('對話框顯示完成');
      })
      .onDisappear(() => {
        console.log('對話框隱藏完成');
      })
      .onWillDismiss(() => {
        console.log('對話框即將關閉');
      })
      .onDidDismiss(() => {
        console.log('對話框已完全關閉');
      })
    }
  }
}

5.2 事件處理最佳實踐

@Component
struct DialogEventHandling {
  @State isShowDialog: boolean = false;
  @State operationResult: string = '';

  // 處理確認操作
  handleConfirm() {
    this.isShowDialog = false;
    this.operationResult = '用户確認了操作';
    this.performAsyncOperation();
  }

  // 處理取消操作
  handleCancel() {
    this.isShowDialog = false;
    this.operationResult = '用户取消了操作';
  }

  // 異步操作示例
  async performAsyncOperation() {
    console.log('開始執行異步操作...');
    // 模擬異步操作
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('異步操作完成');
  }

  build() {
    Column() {
      Button('顯示事件處理對話框')
        .onClick(() => {
          this.isShowDialog = true;
        })
      
      Text(this.operationResult)
        .fontSize(16)
        .margin({ top: 20 })
        .fontColor('#666666')
    }

    if (this.isShowDialog) {
      AlertDialog(
        {
          title: '事件處理示例',
          message: '請選擇您的操作',
          primaryButton: {
            value: '取消',
            action: () => this.handleCancel()
          },
          secondaryButton: {
            value: '確認',
            action: () => this.handleConfirm()
          }
        }
      )
    }
  }
}

六、實戰案例:完整的對話框應用

6.1 多類型對話框管理器

class DialogManager {
  static showAlert(context: any, message: string, confirmText: string = '確定') {
    // 實現alert對話框顯示邏輯
  }

  static showConfirm(context: any, 
                    message: string, 
                    confirmCallback: () => void,
                    cancelCallback?: () => void) {
    // 實現confirm對話框顯示邏輯
  }

  static showCustom(context: any, 
                   builder: CustomDialogController) {
    // 實現自定義對話框顯示邏輯
  }
}

@Entry
@Component
struct DialogDemoApp {
  @State currentDialogType: string = 'none';
  @State dialogResult: string = '';

  build() {
    Column() {
      Text('Dialog組件演示')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 40 })

      // 基礎對話框按鈕組
      ForEach(['alert', 'confirm', 'custom', 'input'], (type: string) => {
        Button(this.getButtonText(type))
          .width('80%')
          .height(50)
          .backgroundColor('#007DFF')
          .fontColor('#FFFFFF')
          .margin({ bottom: 15 })
          .onClick(() => {
            this.showDialog(type);
          })
      })

      // 結果顯示
      if (this.dialogResult) {
        Text('操作結果: ' + this.dialogResult)
          .fontSize(16)
          .margin({ top: 30 })
          .fontColor('#333333')
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  getButtonText(type: string): string {
    const texts: Record<string, string> = {
      'alert': '顯示Alert對話框',
      'confirm': '顯示Confirm對話框', 
      'custom': '顯示自定義對話框',
      'input': '顯示輸入對話框'
    };
    return texts[type] || '未知類型';
  }

  showDialog(type: string) {
    this.currentDialogType = type;
    // 實際實現中這裏會顯示對應的對話框
    this.dialogResult = `顯示了${type}類型的對話框`;
  }
}

七、注意事項和最佳實踐

7.1 重要注意事項

版本兼容性提示

本文示例基於HarmonyOS 4.0及以上版本,部分API在早期版本中可能不可用。請確保您的開發環境與目標設備系統版本匹配。

常見陷阱和解決方案:

  1. 內存泄漏問題
// ❌ 錯誤做法:DialogController未正確釋放
// ✅ 正確做法:在aboutToDisappear中釋放資源
aboutToDisappear() {
  if (this.dialogController) {
    this.dialogController = null;
  }
}
  1. 狀態管理問題
// ❌ 錯誤做法:直接修改props
// ✅ 正確做法:使用@State或@Link管理狀態
@State dialogVisible: boolean = false;
  1. 異步操作處理
// ✅ 最佳實踐:在異步操作前後管理對話框狀態
async handleConfirm() {
  this.showLoadingDialog();
  try {
    await this.performAsyncOperation();
    this.hideDialog();
  } catch (error) {
    this.showErrorDialog(error.message);
  }
}

7.2 性能優化建議

  • 避免在Dialog中加載大量數據或複雜組件
  • 使用條件渲染控制Dialog的顯示/隱藏
  • 對於頻繁使用的Dialog,考慮使用單例模式
  • 合理使用autoCancel屬性提升用户體驗

7.3 用户體驗最佳實踐

  1. 按鈕佈局規範
  • 主要操作按鈕放在右側
  • 破壞性操作使用紅色強調
  • 提供明確的按鈕文案
  1. 內容設計原則
  • 標題簡潔明瞭
  • 消息內容易於理解
  • 避免在Dialog中顯示過多信息
  1. 交互設計
  • 提供明確的關閉方式
  • 支持ESC鍵或返回鍵關閉
  • 適當的動畫效果增強體驗

八、總結

通過本文的學習,您應該已經掌握了:

  • ✅ Dialog組件的基礎使用方法
  • ✅ 各種類型對話框的實現技巧
  • ✅ 自定義Dialog的創建和配置
  • ✅ Dialog生命週期和事件處理
  • ✅ 實際項目中的最佳實踐

下一步學習建議:

  • 深入學習HarmonyOS的其他UI組件
  • 探索Dialog與頁面路由的配合使用
  • 瞭解國際化場景下的Dialog適配
  • 研究Dialog在複雜業務場景中的應用

希望本文能幫助您在HarmonyOS應用開發中熟練使用Dialog組件,打造更好的用户體驗!


版權聲明:本文內容基於HarmonyOS官方文檔編寫,示例代碼遵循Apache 2.0開源協議。 更新日期:2024年12月 適用版本:HarmonyOS 4.0及以上