• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 不依赖UI组件的全局气泡提示 (openPopup)
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @liyi0309-->
5<!--Designer: @liyi0309-->
6<!--Tester: @lxl007-->
7<!--Adviser: @HelloCrease-->
8
9[气泡提示(Popup)](arkts-popup-and-menu-components-popup.md)在使用时依赖绑定UI组件,否则无法使用。从API version 18开始,可以通过使用全局接口[openPopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#openpopup18)的方式,在无UI组件的场景下直接或封装使用,例如在事件回调中使用或封装后对外提供能力。
10
11## 弹出气泡
12
13通过[openPopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#openpopup18)可以弹出气泡。
14
15   ```ts
16   promptAction.openPopup(contentNode, { id: targetId }, {
17     enableArrow: true
18   })
19     .then(() => {
20       console.info('openPopup success');
21     })
22     .catch((err: BusinessError) => {
23       console.error('openPopup error: ' + err.code + ' ' + err.message);
24     })
25   ```
26
27### 创建ComponentContent
28
29   通过调用openPopup接口弹出其气泡,需要提供用于定义自定义弹出框的内容[ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md)。其中,wrapBuilder(buildText)封装自定义组件,new Params(this.message)是自定义组件的入参,可以缺省,也可以传入基础数据类型。
30
31   ```ts
32   private contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message);
33   ```
34
35   如果在wrapBuilder中包含其他组件(例如:[Popup](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Popup.md)、[Chip](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Chip.md)组件),则[ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md#componentcontent-1)应采用带有四个参数的构造函数constructor,其中options参数应传递{ nestingBuilderSupported: true }。
36
37   ```ts
38   @Builder
39   export function buildText(params: Params) {
40     Popup({
41       // 类型设置图标内容
42       icon: {
43         image: $r('app.media.app_icon'),
44         width: 32,
45         height: 32,
46         fillColor: Color.White,
47         borderRadius: 10
48       } as PopupIconOptions,
49       // 设置文字内容
50       title: {
51         text: `This is a Popup title 1`,
52         fontSize: 20,
53         fontColor: Color.Black,
54         fontWeight: FontWeight.Normal
55       } as PopupTextOptions,
56       // 设置文字内容
57       message: {
58         text: `This is a Popup message 1`,
59         fontSize: 15,
60         fontColor: Color.Black
61       } as PopupTextOptions,
62       // 设置按钮内容
63       buttons: [{
64         text: 'confirm',
65         action: () => {
66           console.info('confirm button click');
67         },
68         fontSize: 15,
69         fontColor: Color.Black,
70       },
71         {
72           text: 'cancel',
73           action: () => {
74             console.info('cancel button click');
75           },
76           fontSize: 15,
77           fontColor: Color.Black
78         },] as [PopupButtonOptions?, PopupButtonOptions?]
79     })
80   }
81
82   let contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message, { nestingBuilderSupported: true });
83   ```
84
85
86### 绑定组件信息
87
88   通过调用openPopup接口弹出气泡,需要提供绑定组件的信息[TargetInfo](../reference/apis-arkui/arkts-apis-uicontext-i.md#targetinfo18)。若未传入有效的target,则无法弹出气泡。
89
90   ```ts
91   let frameNode: FrameNode | null = this.ctx.getFrameNodeByUniqueId(this.getUniqueId());
92   let targetId = frameNode?.getChild(0)?.getUniqueId();
93   ```
94
95### 设置弹出气泡样式
96
97   通过调用openPopup接口弹出气泡,可以设置[PopupCommonOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupcommonoptions18类型说明)属性调整气泡样式。
98
99   ```ts
100   private options: PopupCommonOptions = { enableArrow: true };
101   ```
102
103## 更新气泡样式
104
105通过[updatePopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#updatepopup18)可以更新气泡的样式。支持全量更新和增量更新其气泡样式,不支持更新showInSubWindow、focusable、onStateChange、onWillDismiss和transition。
106
107   ```ts
108   promptAction.updatePopup(contentNode, {
109     enableArrow: false
110   }, true)
111     .then(() => {
112       console.info('updatePopup success');
113     })
114     .catch((err: BusinessError) => {
115       console.error('updatePopup error: ' + err.code + ' ' + err.message);
116     })
117   ```
118
119## 关闭气泡
120
121通过调用[closePopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#closepopup18)可以关闭气泡。
122
123   ```ts
124   promptAction.closePopup(contentNode)
125     .then(() => {
126       console.info('closePopup success');
127     })
128     .catch((err: BusinessError) => {
129       console.error('closePopup error: ' + err.code + ' ' + err.message);
130     })
131   ```
132
133> **说明:**
134>
135> 由于[updatePopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#updatepopup18)和[closePopup](../reference/apis-arkui/arkts-apis-uicontext-promptaction.md#closepopup18)依赖content来更新或者关闭指定的气泡,开发者需自行维护传入的content。
136
137
138## 在HAR包中使用全局气泡提示
139
140以下示例通过[HAR](../quick-start/har-package.md)包封装一个Popup,从而对外提供气泡的弹出、更新和关闭能力。
141
142```ts
143// library/src/main/ets/components/MainPage.ets
144
145import { BusinessError } from '@kit.BasicServicesKit';
146import { ComponentContent, TargetInfo, PromptAction } from '@kit.ArkUI';
147
148export class PromptActionClass {
149  private promptAction: PromptAction | null = null;
150  private contentNode: ComponentContent<Object> | null = null;
151  private options: PopupCommonOptions | null = null;
152  private target: TargetInfo | null = null;
153  private isPartialUpdate: boolean = false;
154
155  public setPromptAction(promptAction: PromptAction) {
156    this.promptAction = promptAction;
157  }
158
159  public setContentNode(node: ComponentContent<Object>) {
160    this.contentNode = node;
161  }
162
163  public setTarget(target: TargetInfo) {
164    this.target = target;
165  }
166
167  public setOptions(options: PopupCommonOptions) {
168    this.options = options;
169  }
170
171  public setIsPartialUpdate(isPartialUpdate: boolean) {
172    this.isPartialUpdate = isPartialUpdate;
173  }
174
175  public openPopup() {
176    if (this.promptAction != null) {
177      this.promptAction.openPopup(this.contentNode, this.target, this.options)
178        .then(() => {
179          console.info('openPopup success');
180        })
181        .catch((err: BusinessError) => {
182          console.error('openPopup error: ' + err.code + ' ' + err.message);
183        })
184    }
185  }
186
187  public closePopup() {
188    if (this.promptAction != null) {
189      this.promptAction.closePopup(this.contentNode)
190        .then(() => {
191          console.info('closePopup success');
192        })
193        .catch((err: BusinessError) => {
194          console.error('closePopup error: ' + err.code + ' ' + err.message);
195        })
196    }
197  }
198
199  public updatePopup(options: PopupCommonOptions) {
200    if (this.promptAction != null) {
201      this.promptAction.updatePopup(this.contentNode, options, this.isPartialUpdate)
202        .then(() => {
203          console.info('updatePopup success');
204        })
205        .catch((err: BusinessError) => {
206          console.error('updatePopup error: ' + err.code + ' ' + err.message);
207        })
208    }
209  }
210}
211```
212
213```ts
214// entry/src/main/ets/pages/Index.ets
215
216import { PromptActionClass } from "library";
217import { ComponentContent, PromptAction } from '@kit.ArkUI';
218
219class Params {
220  text: string = "";
221  promptActionClass: PromptActionClass = new PromptActionClass();
222
223  constructor(text: string, promptActionClass: PromptActionClass) {
224    this.text = text;
225    this.promptActionClass = promptActionClass;
226  }
227}
228
229@Builder
230function buildText(params: Params) {
231  Column() {
232    Text(params.text)
233      .fontSize(20)
234      .margin({ top: 10 })
235    Button('Update')
236      .margin({ top: 10 })
237      .width(100)
238      .onClick(() => {
239        params.promptActionClass.updatePopup({
240          enableArrow: false,
241        });
242      })
243    Button('Close')
244      .margin({ top: 10 })
245      .width(100)
246      .onClick(() => {
247        params.promptActionClass.closePopup();
248      })
249  }.width(130).height(150)
250}
251
252@Entry
253@Component
254struct Index {
255  @State message: string = "hello";
256  private uiContext: UIContext = this.getUIContext();
257  private promptAction: PromptAction = this.uiContext.getPromptAction();
258  private promptActionClass: PromptActionClass = new PromptActionClass();
259  private targetId: number = 0;
260  private contentNode: ComponentContent<Object> =
261    new ComponentContent(this.uiContext, wrapBuilder(buildText), new Params(this.message, this.promptActionClass));
262  private options: PopupCommonOptions = { enableArrow: true };
263
264  build() {
265    Column() {
266      Button("openPopup")
267        .margin({ top: 50, left: 100 })
268        .onClick(() => {
269          let frameNode: FrameNode | null = this.uiContext.getFrameNodeByUniqueId(this.getUniqueId());
270          let targetId = frameNode?.getChild(0)?.getUniqueId();
271          if (targetId == undefined) {
272            this.targetId = 0;
273          } else {
274            this.targetId = targetId;
275          }
276          this.promptActionClass.setPromptAction(this.promptAction);
277          this.promptActionClass.setContentNode(this.contentNode);
278          this.promptActionClass.setOptions(this.options);
279          this.promptActionClass.setIsPartialUpdate(false);
280          this.promptActionClass.setTarget({ id: this.targetId });
281          this.promptActionClass.openPopup();
282        })
283    }
284  }
285}
286```
287
288![image](figures/UIopenPopup.gif)
289