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