HarmonyOS CustomDialogController可否拦截返回事件?

我们应用有些功能会在运行期间展示全屏的加载动画自定义弹窗,此时需要拦截用户的返回手势和返回键,以规避用户的误操作损坏机器的行为。

我试了一下CustomDialogController里面的autoCancel: false以及去掉cancel事件回调去掉,但手势一返回弹窗就消失了。

NavDestination里面有onBackPressed拦截,但它与Navigation配套,恐怕无法跟自定义弹窗一起使用吧?

有方法能在自定义弹窗出现的时候屏蔽掉返回事件吗?

HarmonyOS
2024-10-29 10:32:01
浏览
已于2024-10-29 10:32:09修改
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
superinsect

​目前有两种方式实现您的需求:

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

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

方法2的实现代码如下:​

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

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
微信
回复
2024-10-29 17:11:03
相关问题
HarmonyOS RN如何拦截返回事件
16浏览 • 1回复 待解决
HarmonyOS 侧滑返回事件拦截与绑定
1158浏览 • 1回复 待解决
CustomDialogController禁用返回
310浏览 • 1回复 待解决
HarmonyOS 怎么拦截返回键盘
310浏览 • 1回复 待解决
WebView goBack事件拦截
1037浏览 • 1回复 待解决
webview拦截返回按钮。
789浏览 • 1回复 待解决
HarmonyOS UI组件事件拦截处理
364浏览 • 1回复 待解决
HarmonyOS如何拦截list的滑动事件
340浏览 • 1回复 待解决
HarmonyOS 拦截系统返回手势问题
455浏览 • 1回复 待解决
Slider拦截点击事件失败
261浏览 • 1回复 待解决
如何拦截onTouch事件传递
649浏览 • 1回复 待解决
鸿蒙事件拦截分发处理
10417浏览 • 2回复 待解决