• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 页面级弹出框
2ArkUI的弹出框默认设置为全局级别,弹窗节点作为页面根节点的子节点,显示层级高于应用中的所有路由/导航页面。当页面内进行路由跳转时,如果应用未主动调用close方法关闭弹出框,弹出框不会自动关闭,并且会在下一个跳转页面上继续显示。
3
4从API version 15开始,如果开发者希望在路由跳转后,弹出框能够随前一个路由页面的切换而消失,并在路由返回后弹出框能够继续正常显示,可以通过页面级弹出框来实现。
5
6> **说明:**
7>
8> 当且仅当弹出框为非子窗模式时,页面级能力才会生效。即showInSubWindow参数不设置或设置为false。
9>
10> 页面级弹出框一般和导航路由能力结合使用,可以通过[组件导航和页面路由概述](arkts-navigation-introduction.md)了解相关术语。
11>
12> 页面级弹出框的使用方式是在当前弹出框的入参之中新增了相关属性能力,使用前可以通过[弹出框概述](arkts-base-dialog-overview.md)了解基础的弹出框使用方法。
13
14
15## 设置页面级弹出框参数
16
17> **说明:**
18>
19> 详细变量定义请参考[完整示例](#完整示例)。
20
21在弹出框的options入参中设置[levelMode](../reference/apis-arkui/js-apis-promptAction.md#levelmode15)属性,值为LevelMode.EMBEDDED表示开启页面级弹出框能力。
22
23当弹出框弹出时,会自动获取当前显示的Page页面并将弹出框节点挂载在此页面下。此时弹出框的显示层级高于此Page页面下的所有Navigation页面。
24
25```ts
26this.getUIContext().getPromptAction().openCustomDialog({
27  builder: () => {
28    this.customDialogComponent();
29  },
30  levelMode: LevelMode.EMBEDDED, // 启用页面级弹出框
31})
32```
33
34## 弹出框在指定页面内弹出
35
36如果希望弹出框显示在某个指定页面内,需通过第二个参数levelUniqueId来实现。此参数接收页面内的节点id,设置后,弹出框显示时会自动查询此id对应的节点所在的Navigation页面,并将其挂载在此页面下。
37
38如下代码示例所示,Text节点为指定页面的节点,设置自定义id后,通过[getFrameNodeById](../reference/apis-arkui/js-apis-arkui-UIContext.md#getframenodebyid12)方法获取该节点,再通过[getUniqueId](../reference/apis-arkui/js-apis-arkui-frameNode.md#getuniqueid12)获取节点的内部id,并将其作为levelUniqueId的值传入。
39
40```ts
41Text(this.message).id("test_text")
42  .onClick(() => {
43    const node: FrameNode | null = this.getUIContext().getFrameNodeById("test_text") || null;
44    this.getUIContext().getPromptAction().openCustomDialog({
45      builder: () => {
46        this.customDialogComponent();
47      },
48      levelMode: LevelMode.EMBEDDED, // 启用页面级弹出框
49      levelUniqueId: node?.getUniqueId(), // 设置页面级弹出框所在页面的任意节点ID
50    })
51  })
52```
53
54## 设置页面级弹出框蒙层样式
55
56如果弹出框配置了蒙层,蒙层的遮盖范围会根据页面层级的变化进行调整,默认遮罩范围为弹出框父节点的显示区域(Page页面或者Navigation页面)。此时,状态栏和导航条不会被蒙层遮挡。若希望遮挡状态栏和导航条,可将[immersiveMode](../reference/apis-arkui/js-apis-promptAction.md#immersivemode15)参数的值设为ImmersiveMode.EXTEND57
58```ts
59Text(this.message).id("test_text")
60  .onClick(() => {
61    const node: FrameNode | null = this.getUIContext().getFrameNodeById("test_text") || null;
62    this.getUIContext().getPromptAction().openCustomDialog({
63      builder: () => {
64        this.customDialogComponent();
65      },
66      levelMode: LevelMode.EMBEDDED, // 启用页面级弹出框
67      levelUniqueId: node?.getUniqueId(), // 设置页面级弹出框所在页面的任意节点ID
68      immersiveMode: ImmersiveMode.EXTEND, // 设置页面级弹出框蒙层的显示模式
69    })
70  })
71```
72
73## 交互说明
74
75页面内弹出框在部分交互逻辑上依然遵循部分弹出框指定的交互策略:
76
771. 侧滑时先关闭弹出框。通过侧滑手势返回上一页时,如果页面上存在弹出框,弹出框会优先关闭并结束本次手势行为。如果期望返回上一页,需要再次出发侧滑手势。
78
792. 点击弹出框的蒙层,默认会关闭弹出框,点击蒙层以外的区域则不会。
80
81## 完整示例
82```ts
83// Index.ets
84import { LevelMode, ImmersiveMode } from '@kit.ArkUI';
85
86let customDialogId: number = 0;
87
88@Builder
89function customDialogBuilder(uiContext: UIContext) {
90  Column() {
91    Text('Custom dialog Message').fontSize(20).height(100)
92    Row() {
93      Button("Next").onClick(() => {
94        // 在弹窗内部进行路由跳转。
95        uiContext.getRouter().pushUrl({url: 'pages/Next'});
96      })
97      Blank().width(50)
98      Button("Close").onClick(() => {
99        uiContext.getPromptAction().closeCustomDialog(customDialogId);
100      })
101    }
102  }.padding(20)
103}
104
105@Entry
106@Component
107struct Index {
108  @State message: string = 'Hello World';
109  private uiContext: UIContext = this.getUIContext();
110
111  @Builder
112  customDialogComponent() {
113    customDialogBuilder(this.uiContext);
114  }
115
116  build() {
117    Row() {
118      Column() {
119        Text(this.message).id("test_text")
120          .fontSize(50)
121          .fontWeight(FontWeight.Bold)
122          .onClick(() => {
123            const node: FrameNode | null = this.getUIContext().getFrameNodeById("test_text") || null;
124            this.uiContext.getPromptAction().openCustomDialog({
125              builder: () => {
126                this.customDialogComponent();
127              },
128              levelMode: LevelMode.EMBEDDED, // 启用页面级弹出框
129              levelUniqueId: node?.getUniqueId(), // 设置页面级弹出框所在页面的任意节点ID
130              immersiveMode: ImmersiveMode.EXTEND, // 设置页面级弹出框蒙层的显示模式
131            }).then((dialogId: number) => {
132              customDialogId = dialogId;
133            })
134          })
135      }
136      .width('100%')
137    }
138    .height('100%')
139  }
140}
141```
142```ts
143// Next.ets
144@Entry
145@Component
146struct Next {
147  @State message: string = 'Back';
148
149  build() {
150    Row() {
151      Column() {
152        Button(this.message)
153          .fontSize(20)
154          .fontWeight(FontWeight.Bold)
155          .onClick(() => {
156            this.getUIContext().getRouter().back();
157          })
158      }
159      .width('100%')
160    }
161    .height('100%')
162  }
163}
164```
165![embedded_dialog](figures/embedded_dialog.gif)