文档管理中心

PC端点击Dock栏关闭窗口时,如何弹窗确认

问题现象

HarmonyOS PC端应用最小化Dock栏后,如何在应用右键点击关闭窗口时,增加一个二次确认弹窗给到用户操作。

背景知识

  • onPrepareToTerminate:在UIAbility即将关闭前(例如用户通过点击应用窗口右上角的关闭按钮、或者通过Dock栏/托盘右键退出应用时),系统会触发该回调,用于在UIAbility正式关闭前执行其他操作。
  • 开发者可以在onPrepareToTerminate回调中返回true阻拦此次关闭,然后在合适时机主动调用terminateSelf接口关闭。
  • showDialog:创建并显示对话框,对话框响应结果使用callback异步回调返回。

解决方案

HarmonyOS PC端应用最小化Dock栏后,可以通过监听onPrepareToTerminate回调,在触发右键点击关闭窗口时,恢复主窗口并弹窗通知用户二次确认后再关闭窗口。

  • 在module.json5配置文件中声明ohos.permission.PREPARE_APP_TERMINATE权限。
    收起
    自动换行
    深色代码主题
    复制
    1. "requestPermissions":[
    2. {
    3. "name" : "ohos.permission.PREPARE_APP_TERMINATE"
    4. }
    5. ],
  • 在EntryAbility.ets文件中添加onPrepareToTerminate回调事件,在Dock栏关闭窗口时,进行弹窗提示。
    收起
    自动换行
    深色代码主题
    复制
    1. import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit';
    2. import { hilog } from '@kit.PerformanceAnalysisKit';
    3. import { window } from '@kit.ArkUI';
    4. import { BusinessError } from '@kit.BasicServicesKit';
    5. const DOMAIN = 0x0000;
    6. export default class EntryAbility extends UIAbility {
    7. //当前window对象
    8. private currentWindowStage: window.WindowStage | null = null;
    9. onCreate(): void {
    10. this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    11. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
    12. }
    13. onDestroy(): void {
    14. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
    15. }
    16. onWindowStageCreate(windowStage: window.WindowStage): void {
    17. // Main window is created, set main page for this ability
    18. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    19. if (this.currentWindowStage === null) {
    20. this.currentWindowStage = windowStage;
    21. }
    22. // 存储windowStage
    23. AppStorage.setOrCreate('windowStage', windowStage);
    24. windowStage.loadContent('pages/Index', (err) => {
    25. // 存储windowStatus
    26. AppStorage.setOrCreate('windowStatus', window.WindowStatusType.FULL_SCREEN);
    27. windowStage.getMainWindow((err: BusinessError, data) => {
    28. if (err) {
    29. // To do sth.
    30. }
    31. let windowClass = data;
    32. windowClass.on('windowStatusChange', (windowStatusType) => {
    33. AppStorage.setOrCreate('windowStatus', windowStatusType);
    34. });
    35. });
    36. if (err.code) {
    37. hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
    38. return;
    39. }
    40. hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    41. });
    42. }
    43. onWindowStageDestroy(): void {
    44. // Main window is destroyed, release UI related resources
    45. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
    46. }
    47. onForeground(): void {
    48. // Ability has brought to foreground
    49. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
    50. }
    51. onBackground(): void {
    52. // Ability has back to background
    53. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
    54. }
    55. onPrepareToTerminate(): boolean {
    56. // 开发者定义预关闭动作
    57. hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onPrepareToTerminate');
    58. // 例如关闭应用之前弹窗提示是否关闭app
    59. let windowStatus = AppStorage.get('windowStatus') as window.WindowStatusType;
    60. if (windowStatus == window.WindowStatusType.MINIMIZE) {
    61. let mainWindowClass = this.currentWindowStage?.getMainWindowSync() as window.Window;
    62. let promise = mainWindowClass.restore();
    63. promise.then(() => {
    64. console.info('Succeeded in restoring the window.');
    65. if (this.currentWindowStage !== null) {
    66. this.currentWindowStage?.getMainWindowSync().getUIContext().getPromptAction().showDialog({
    67. title: '提示',
    68. message: '确认是否关闭APP?',
    69. buttons: [
    70. {
    71. text: '取消',
    72. color: '#0091FF'
    73. },
    74. {
    75. text: '确定',
    76. color: '#ff0000'
    77. }
    78. ]
    79. }).then(data => {
    80. if (data.index === 0) {
    81. this.currentWindowStage?.getMainWindowSync().getUIContext().getPromptAction().showToast({
    82. message: '已取消',
    83. duration: 2000
    84. });
    85. } else {
    86. // 确认关闭
    87. this.context.terminateSelf();
    88. }
    89. });
    90. }
    91. }).catch((err: BusinessError) => {
    92. console.error(`Failed to restore the window. Cause code: ${err.code},
    93. message: ${err.message}`);
    94. });
    95. return true;
    96. } else {
    97. if (this.currentWindowStage !== null) {
    98. this.currentWindowStage?.getMainWindowSync().getUIContext().getPromptAction().showDialog({
    99. title: '提示',
    100. message: '确认是否关闭APP?',
    101. buttons: [
    102. {
    103. text: '取消',
    104. color: '#0091FF'
    105. },
    106. {
    107. text: '确定',
    108. color: '#ff0000'
    109. }
    110. ]
    111. }).then(data => {
    112. if (data.index === 0) {
    113. this.currentWindowStage?.getMainWindowSync().getUIContext().getPromptAction().showToast({
    114. message: '已取消',
    115. duration: 2000
    116. });
    117. } else {
    118. // 确认关闭
    119. this.context.terminateSelf();
    120. }
    121. });
    122. }
    123. }
    124. return true;
    125. }
    126. };