在HarmonyOS NEXT开发中如何实现类似DialogActivity的效果?

在HarmonyOS NEXT开发中如何实现类似DialogActivity的效果?需要跳转一个Page,但是希望这个Page的样式是一个Dialog样式

阅读 581
avatarAI BotBETA

在HarmonyOS NEXT开发中,要实现类似Android中DialogActivity的效果,即跳转到一个页面(Page),但希望这个页面的样式是一个Dialog样式,你可以使用Ability结合模态对话框(Modal Dialog)来实现。以下是一个基本的实现步骤和示例代码:

步骤

  1. 创建Dialog样式的Page
    创建一个新的Page,并在其布局文件中定义一个Dialog样式的布局。
  2. 在Ability中启动Dialog样式的Page
    使用Intent启动这个Page,并通过设置启动参数使其以Dialog样式显示。

示例代码

1. 创建Dialog样式的Page

首先,创建一个新的Page,例如DialogPage

DialogPage.hml (布局文件):

<div class="container">
  <text class="title">This is a Dialog Page</text>
  <!-- 其他布局内容 -->
</div>

DialogPage.css (样式文件):

.container {
  width: 80%;
  height: auto;
  background-color: white;
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.title {
  font-size: 20px;
  font-weight: bold;
  text-align: center;
}

DialogPage.js (逻辑文件):

export default {
  data: {
    // 数据定义
  },
  onInit() {
    // 初始化逻辑
  },
  // 其他方法
};

2. 在Ability中启动Dialog样式的Page

在你的主Ability中,使用Intent启动DialogPage,并通过设置启动参数使其以Dialog样式显示。

MainAbility.js (逻辑文件):

import featureAbility from '@ohos.ability.featureAbility';

export default {
  data: {
    // 数据定义
  },
  onShow() {
    this.showDialogPage();
  },
  showDialogPage() {
    let intent = new featureAbility.Intent();
    intent.setElement(new featureAbility.ElementName('com.example.yourapp', 'com.example.yourapp.DialogPage'));
    intent.setFlags(featureAbility.Intent.FLAG_ACTIVITY_NEW_TASK);

    // 这里假设你有一个方法来显示Dialog样式的Page,具体实现可能需要自定义
    // 例如,可以通过设置Window的属性来模拟Dialog效果,但这在HarmonyOS中可能有所不同
    // 一种方法是使用模态对话框API,但HarmonyOS的API可能与Android有所不同,需要查阅具体文档
    // 这里为了简化,我们直接启动Page,实际开发中可能需要进一步调整以实现Dialog效果

    // 启动Page(注意:这里不会直接显示为Dialog,需要进一步自定义实现)
    featureAbility.startAbility(intent);
  },
  // 其他方法
};

注意:在HarmonyOS中,直接通过启动一个Page来实现Dialog效果可能不如在Android中直接。你可能需要进一步自定义Window属性或使用模态对话框API(如果存在)来实现Dialog效果。由于HarmonyOS的API和框架与Android有所不同,建议查阅HarmonyOS的官方文档以获取更详细和准确的信息。

如果HarmonyOS提供了模态对话框API,你可以考虑使用这些API来创建一个Dialog,并在Dialog中加载你的自定义布局,以实现类似DialogActivity的效果。

1 个回答

可以使用自定义弹窗组件来实现效果。参考地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-refere...示例PageB直接为一个空页面,在页面的 aboutToAppear()方法中打开自定义弹窗,弹窗内部按钮加上router.back()方法,处理完本身逻辑后返回PageA。
PageA在entry包下:

import { router } from '@kit.ArkUI'; 
 
import('library_hsp/src/main/ets/pages/PageB'); // 引入共享包中的命名路由页面 
 
@Entry({ routeName: "PageA" }) 
@Component 
struct PageA { 
  @State message: string = 'PageA'; 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(32) 
          .fontWeight(FontWeight.Bold) 
 
        Button("进入B页面").onClick(() => { 
          router.pushNamedRoute({ 
            name: 'PageB' 
          }) 
        }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

PageB在HSP包下:

import { router } from '@kit.ArkUI' 
 
@CustomDialog 
struct CustomDialogExample { 
  @Link textValue: string 
  @Link inputValue: string 
  controller?: CustomDialogController 
  // 若尝试在CustomDialog中传入多个其他的Controller,以实现在CustomDialog中打开另一个或另一些CustomDialog,那么此处需要将指向自己的controller放在所有controller的后面 
  cancel: () => void = () => { 
  } 
  confirm: () => void = () => { 
  } 
 
  build() { 
    Column() { 
      Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 
      TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%') 
        .onChange((value: string) => { 
          this.textValue = value 
        }) 
      Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 }) 
      Flex({ justifyContent: FlexAlign.SpaceAround }) { 
        Button('cancel') 
          .onClick(() => { 
            if (this.controller != undefined) { 
              this.controller.close() 
              this.cancel() 
            } 
          }).backgroundColor(0xffffff).fontColor(Color.Black) 
        Button('confirm') 
          .onClick(() => { 
            if (this.controller != undefined) { 
              this.inputValue = this.textValue 
              this.controller.close() 
              this.confirm() 
            } 
          }).backgroundColor(0xffffff).fontColor(Color.Red) 
      }.margin({ bottom: 10 }) 
 
    }.borderRadius(10) 
 
  } 
} 
 
@Entry({ routeName: 'PageB' }) 
@Component 
export struct PageB { 
  @State textValue: string = '' 
  @State inputValue: string = 'click me' 
  dialogController: CustomDialogController | null = new CustomDialogController({ 
    builder: CustomDialogExample({ 
      cancel: () => { 
        this.onCancel() 
      }, 
      confirm: () => { 
        this.onAccept() 
      }, 
      textValue: $textValue, 
      inputValue: $inputValue 
    }), 
    cancel: this.exitApp, 
    autoCancel: true, 
    alignment: DialogAlignment.Bottom, 
    offset: { dx: 0, dy: -20 }, 
    gridCount: 4, 
    customStyle: false, 
    cornerRadius: 10, 
  }) 
 
  aboutToAppear(): void { 
    this.dialogController?.open() 
  } 
 
  // 在自定义组件即将析构销毁时将dialogControlle置空 
  aboutToDisappear() { 
    this.dialogController = null // 将dialogController置空 
  } 
 
  onCancel() { 
    console.info('Callback when the first button is clicked') 
    router.back() 
  } 
 
  onAccept() { 
    console.info('Callback when the second button is clicked') 
    router.back() 
  } 
 
  exitApp() { 
    console.info('Click the callback in the blank area') 
  } 
 
  build() { 
    Column() { 
    }.width('100%').margin({ top: 5 }) 
  } 
}

可以把弹窗页代码编写成自定义弹窗格式合入到打开弹窗页的入口页的module中,然后使用自定义弹窗的方法来谈起弹窗页。通过router跳转后,新页面透明底下印出入口页面是做不到的。如果不用自定义弹窗,也可以自定义一个组件通过stack布局放置在入口页面前,并设置该组件visibility属性来先隐藏该页面,需要谈起弹窗后,再设置visibility为可见,达到伪弹窗的效果。这种情况的前提也是代码入口页与弹窗页代码再同一个页面进行显隐。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
HarmonyOS
子站问答
访问
宣传栏