HarmonyOS 显示的对话框如何处理返回键消失的问题

我现在想显示一个对话框,通过CustomDialogController方式显示出来了,想禁止用户按返回键消失,但是目前好像没找到相关的API,请问有什么办法处理么?

HarmonyOS
1天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
aquaa

目前有两种方式实现:

1.使用Stack组件实现自定义弹窗。

2.使用NavDestination的Dialog模式实现自定义弹窗。

方法2的实现代码如下:

Index.ets

import { AppRouter } from './AppRouter'
import { AppDialog } from './AppDialog'
import { PrivacyDialogViewBuilder } from './PrivacyDialogView';
import { DefaultDialog } from './DefaultDialog';

@Entry
@Component
struct Index {
  @Builder
  PageMap(name: string) {
    DefaultDialog()
  }

  build() {
    Navigation(AppRouter.getInstance().getPathStack()) {
      Stack({ alignContent: Alignment.Center }) {
        Column() {
          Button('基于Navigation实现自定义弹窗', {
            stateEffect: true,
            type: ButtonType.Capsule
          })
            .onClick(() => {
              AppDialog
                .build(wrapBuilder(PrivacyDialogViewBuilder))
                .onBackPressed((): boolean => true)
                .open();
            })
        }
      }
      .height('100%')
      .width('100%')
    }
    .hideTitleBar(true)
    .navDestination(this.PageMap)
  }
}

PrivacyDialogView.ets

import { AppDialog } from './AppDialog'

@Builder
export function PrivacyDialogViewBuilder() {
  PrivacyDialogView()
}

@Component
struct PrivacyDialogView {
  scroller: Scroller = new Scroller()

  build() {
    Column() {
      Text('温馨提示')
        .fontSize(18)
        .padding(15)

      Scroll(this.scroller) {
        Text('请您知悉,同意隐私政策仅代表您已了解应用提供功能,以及功能运行所需的必要个人信息。')
          .fontSize(16)
          .padding(15)
      }
      .scrollable(ScrollDirection.Vertical)
      .height(240)

      Button('同意', { type: ButtonType.Capsule })
        .onClick(() => {
          AppDialog.instance.close();
        })
        .margin({ top: 10, bottom: 10 })
        .width('80%')

      Button('不同意', {
        stateEffect: false,
        buttonStyle: ButtonStyleMode.TEXTUAL
      })
        .onClick(() => {
          AppDialog.instance.close();
        })
        .margin({ bottom: 10 })
    }
    .backgroundColor(Color.White)
    .borderRadius(15)
    .width(250)
  }
}

DefaultDialog.ets

import { AppRouter } from './AppRouter';
import { AppDialog, AppDialogOption } from './AppDialog';

@Component
export struct DefaultDialog {
  private dialogOptions?: AppDialogOption;

  @State
  opacityNum: number = 1;

  aboutToAppear(): void {
    this.dialogOptions = AppRouter.getLastParams() as AppDialogOption;
  }

  build() {
    NavDestination() {
      Stack({ alignContent: this.dialogOptions?.styles?.align }) {
        Column() {}
        .width('100%')
        .height('100%')
        .backgroundColor(this.dialogOptions?.styles?.background)
        .opacity(this.opacityNum)
        .transition(
          TransitionEffect.OPACITY.animation({
            duration: 300,
            curve: Curve.Friction
          })
        )
        .onClick(() => {
          let res = false;
          if (this.dialogOptions?.onBackPressed) {
            res = this.dialogOptions?.onBackPressed();
          }
          if (res) {
            return;
          }
          animateTo(
            {
              duration: 300,
              curve: Curve.Friction,
              onFinish: () => {
                AppDialog.instance.close();
              }
            },
            () => {
              this.opacityNum = 0
            }
          )
        })

        Column() {
          this.dialogOptions?.view?.builder(this.dialogOptions?.params)
        }
        .opacity(this.opacityNum)
        .transition(
          TransitionEffect.scale({ x: 0, y: 0 }).animation({
            duration: 300,
            curve: Curve.Friction
          })
        )
      }
      .width('100%')
      .height('100%')
    }
    .mode(NavDestinationMode.DIALOG)
    .hideTitleBar(true)
    .onBackPressed(this.dialogOptions?.onBackPressed)
  }
}

AppDialog.ets

import { AppRouter } from './AppRouter';

export class AppDialog {
  static instance: AppDialog;
  private lastIndex: number = 0;
  private options?: AppDialogOption;

  public static buildWithOptions(options?: AppDialogOption): AppDialog {
    let instance: AppDialog = new AppDialog();
    instance.lastIndex = AppRouter.getInstance().getPathStack().size() - 1;
    instance.options = options;
    AppDialog.instance = instance;
    return instance;
  }

  public static build(builder: WrappedBuilder<Object[]>): AppDialog {
    let options: AppDialogOption = new AppDialogOption();
    options.view = builder;
    return AppDialog.buildWithOptions(options);
  }

  public static closeAll(): void {
    AppRouter.getInstance().getPathStack().removeByName('defaultDialog');
  }

  public open(): AppDialog {
    AppRouter.getInstance().getPathStack().pushPathByName('defaultDialog', this.options);
    return this;
  }

  public onBackPressed(callback: () => boolean): AppDialog {
    this.options!.onBackPressed = callback;
    return this;
  }

  public close(): void {
    if (AppRouter.getInstance().getPathStack().size() >= this.lastIndex) {
      AppRouter.getInstance().getPathStack().popToIndex(this.lastIndex);
    }
  }
}

export class AppDialogOption {
  view?: WrappedBuilder<Object[]>
  params?: Object
  onClose?: () => void
  onPop?: (data: PopInfo) => void
  onBackPressed?: () => boolean
  styles?: AppDialogStyle = new AppDialogStyle()
}

export class AppDialogStyle {
  transparent: boolean = false
  background: string = 'rgba(0,0,0,0.5)'
  radius: Length = 5
  align: Alignment = Alignment.Center
}

AppRouter.ets

import { HashMap } from '@kit.ArkTS';

export interface RouterParams {
  name?: string,
  onPop?: (data: PopInfo) => void
}

export class AppRouter {
  private static instance = new AppRouter();
  private pathStack: NavPathStack = new NavPathStack();
  private routeMap: HashMap<string, WrappedBuilder<[object]>> = new HashMap();

  public static getInstance(): AppRouter {
    return AppRouter.instance;
  }

  public getPathStack(): NavPathStack {
    return this.pathStack;
  }

  public addRouteMap(name: string, builder: WrappedBuilder<[object]>): void {
    this.routeMap.set(name, builder)
  }

  private pushPath(name: string): void {
    this.pathStack.pushPath({ name: name })
  }

  public static push(name: string): void {
    AppRouter.instance.pushPath(name);
  }

  public static openDialog(name: string, params?: RouterParams): void {
    AppRouter.instance.pathStack.pushPath({
      name: name,
      param: params,
      onPop: (data: PopInfo) => {
        if (params?.onPop) {
          params.onPop!(data);
        }
      }
    });
  }

  public static replace(name: string, params?: RouterParams): void {
    AppRouter.instance.pathStack.replacePath({
      name: name,
      param: params
    });
  }

  public static getParams(name: string): string {
    return JSON.stringify(AppRouter.instance.pathStack.getParamByName(name));
  }

  public static getLastParams(): Object {
    return AppRouter.instance.pathStack.getParamByIndex(AppRouter.instance.pathStack.size()-1) as Object;
  }

  public static pop(): void {
    AppRouter.instance.pathStack.pop();
  }

  public static popWithResult(params: RouterParams): void {
    AppRouter.instance.pathStack.pop(params);
  }
}

新建工程,上述代码创建ets文件复制进去,放在Index.ets同级目录,即可编译运行。

分享
微博
QQ
微信
回复
1天前
相关问题
HarmonyOS 页面跳转后对话框消失
53浏览 • 1回复 待解决
HarmonyOS class中创建对话框不能显示
93浏览 • 1回复 待解决
HarmonyOS 弹出对话框
47浏览 • 1回复 待解决
HarmonyOS 对话框弹出页面被遮挡
93浏览 • 1回复 待解决
如何封装一个自定义Dialog对话框
2268浏览 • 1回复 待解决