1# 气泡提示(Popup) 2Popup属性可绑定在组件上显示气泡弹窗提示,设置弹窗内容、交互逻辑和显示状态。主要用于屏幕录制、信息弹出提醒等显示状态。 3 4气泡分为两种类型,一种是系统提供的气泡[PopupOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupoptions类型说明),一种是开发者可以自定义的气泡[CustomPopupOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#custompopupoptions8类型说明)。其中,PopupOptions通过配置primaryButton和secondaryButton来设置带按钮的气泡,CustomPopupOptions通过配置[builder](../../application-dev/quick-start/arkts-builder.md)来设置自定义的气泡。 5 6气泡可以通过配置[mask](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupoptions类型说明)来实现模态和非模态窗口,mask为true或者颜色值的时候,气泡为模态窗口,mask为false时,气泡为非模态窗口。 7 8## 文本提示气泡 9 10文本提示气泡常用于只展示带有文本的信息提示,不带有任何交互的场景。Popup属性需绑定组件,当bindPopup属性中参数show为true时会弹出气泡提示。 11 12在Button组件上绑定Popup属性,每次点击Button按钮,handlePopup会切换布尔值,当值为true时,触发bindPopup弹出气泡。 13 14```ts 15@Entry 16@Component 17struct PopupExample { 18 @State handlePopup: boolean = false 19 20 build() { 21 Column() { 22 Button('PopupOptions') 23 .onClick(() => { 24 this.handlePopup = !this.handlePopup 25 }) 26 .bindPopup(this.handlePopup, { 27 message: 'This is a popup with PopupOptions', 28 }) 29 }.width('100%').padding({ top: 5 }) 30 } 31} 32``` 33 34 35 36## 添加气泡状态变化的事件 37 38通过onStateChange参数为气泡添加状态变化的事件回调,可以判断当前气泡的显示状态。 39 40```ts 41@Entry 42@Component 43struct PopupExample { 44 @State handlePopup: boolean = false 45 46 build() { 47 Column() { 48 Button('PopupOptions') 49 .onClick(() => { 50 this.handlePopup = !this.handlePopup 51 }) 52 .bindPopup(this.handlePopup, { 53 message: 'This is a popup with PopupOptions', 54 onStateChange: (e)=> { // 返回当前的气泡状态 55 if (!e.isVisible) { 56 this.handlePopup = false 57 } 58 } 59 }) 60 }.width('100%').padding({ top: 5 }) 61 } 62} 63``` 64 65 66 67## 带按钮的提示气泡 68 69通过primaryButton、secondaryButton属性为气泡最多设置两个Button按钮,通过此按钮进行简单的交互,开发者可以通过配置action参数来设置想要触发的操作。 70 71```ts 72@Entry 73@Component 74struct PopupExample22 { 75 @State handlePopup: boolean = false 76 77 build() { 78 Column() { 79 Button('PopupOptions').margin({ top: 200 }) 80 .onClick(() => { 81 this.handlePopup = !this.handlePopup 82 }) 83 .bindPopup(this.handlePopup, { 84 message: 'This is a popup with PopupOptions', 85 primaryButton: { 86 value: 'Confirm', 87 action: () => { 88 this.handlePopup = !this.handlePopup 89 console.info('confirm Button click') 90 } 91 }, 92 secondaryButton: { 93 value: 'Cancel', 94 action: () => { 95 this.handlePopup = !this.handlePopup 96 } 97 }, 98 onStateChange: (e) => { 99 if (!e.isVisible) { 100 this.handlePopup = false 101 } 102 } 103 }) 104 }.width('100%').padding({ top: 5 }) 105 } 106} 107``` 108 109 110 111## 气泡的动画 112 113气泡通过定义transition控制气泡的进场和出场动画效果。 114 115```ts 116// xxx.ets 117@Entry 118@Component 119struct PopupExample { 120 @State handlePopup: boolean = false 121 @State customPopup: boolean = false 122 123 // popup构造器定义弹框内容 124 @Builder popupBuilder() { 125 Row() { 126 Text('Custom Popup with transitionEffect').fontSize(10) 127 }.height(50).padding(5) 128 } 129 130 build() { 131 Flex({ direction: FlexDirection.Column }) { 132 // PopupOptions 类型设置弹框内容 133 Button('PopupOptions') 134 .onClick(() => { 135 this.handlePopup = !this.handlePopup 136 }) 137 .bindPopup(this.handlePopup, { 138 message: 'This is a popup with transitionEffect', 139 placementOnTop: true, 140 showInSubWindow: false, 141 onStateChange: (e) => { 142 if (!e.isVisible) { 143 this.handlePopup = false 144 } 145 }, 146 // 设置弹窗显示动效为透明度动效与平移动效的组合效果,无退出动效 147 transition:TransitionEffect.asymmetric( 148 TransitionEffect.OPACITY.animation({ duration: 1000, curve: Curve.Ease }).combine( 149 TransitionEffect.translate({ x: 50, y: 50 })), 150 TransitionEffect.IDENTITY) 151 }) 152 .position({ x: 100, y: 150 }) 153 154 // CustomPopupOptions 类型设置弹框内容 155 Button('CustomPopupOptions') 156 .onClick(() => { 157 this.customPopup = !this.customPopup 158 }) 159 .bindPopup(this.customPopup, { 160 builder: this.popupBuilder, 161 placement: Placement.Top, 162 showInSubWindow: false, 163 onStateChange: (e) => { 164 if (!e.isVisible) { 165 this.customPopup = false 166 } 167 }, 168 // 设置弹窗显示动效与退出动效为缩放动效 169 transition:TransitionEffect.scale({ x: 1, y: 0 }).animation({ duration: 500, curve: Curve.Ease }) 170 }) 171 .position({ x: 80, y: 300 }) 172 }.width('100%').padding({ top: 5 }) 173 } 174} 175``` 176 177 178 179## 自定义气泡 180 181开发者可以使用CustomPopupOptions的builder创建自定义气泡,\@Builder中可以放自定义的内容。除此之外,还可以通过popupColor等参数控制气泡样式。 182 183```ts 184@Entry 185@Component 186struct Index { 187 @State customPopup: boolean = false 188 // popup构造器定义弹框内容 189 @Builder popupBuilder() { 190 Row({ space: 2 }) { 191 Image($r("app.media.icon")).width(24).height(24).margin({ left: 5 }) 192 Text('This is Custom Popup').fontSize(15) 193 }.width(200).height(50).padding(5) 194 } 195 build() { 196 Column() { 197 Button('CustomPopupOptions') 198 .position({x:100,y:200}) 199 .onClick(() => { 200 this.customPopup = !this.customPopup 201 }) 202 .bindPopup(this.customPopup, { 203 builder: this.popupBuilder, // 气泡的内容 204 placement:Placement.Bottom, // 气泡的弹出位置 205 popupColor:Color.Pink, // 气泡的背景色 206 onStateChange: (e) => { 207 if (!e.isVisible) { 208 this.customPopup = false 209 } 210 } 211 }) 212 } 213 .height('100%') 214 } 215} 216``` 217 218使用者通过配置placement参数将弹出的气泡放到需要提示的位置。弹窗构造器会触发弹出提示信息,来引导使用者完成操作,也让使用者有更好的UI体验。 219 220 221 222## 气泡样式 223 224气泡除了可以通过builder实现自定义气泡,还可以通过接口设置气泡的样式和显示效果。 225 226背景颜色:气泡的背景色默认为透明,但是会有一个默认的模糊效果,手机上为COMPONENT\_ULTRA\_THICK。 227蒙层样式:气泡默认有蒙层,且蒙层的颜色为透明。 228显示大小:气泡大小有内部的builder大小或者message的长度决定的。 229显示位置:气泡默认显示在宿主组件的下方,可以通过Placement接口来配置其显示位置以及对齐方向。 230以下示例通过设置popupColor(背景颜色)、mask(蒙层样式)、width(气泡宽度)、placement(显示位置)实现气泡的样式。 231 232```ts 233// xxx.ets 234 235@Entry 236@Component 237struct PopupExample { 238 @State handlePopup: boolean = false 239 240 build() { 241 Column({ space: 100 }) { 242 Button('PopupOptions') 243 .onClick(() => { 244 this.handlePopup = !this.handlePopup 245 }) 246 .bindPopup(this.handlePopup, { 247 width: 200, 248 message: 'This is a popup.', 249 popupColor: Color.Red, // 设置气泡的背景色 250 mask: { 251 color: '#33d9d9d9' 252 }, 253 placement: Placement.Top, 254 backgroundBlurStyle: BlurStyle.NONE // 去除背景模糊效果需要关闭气泡的模糊背景 255 }) 256 } 257 .width('100%') 258 } 259} 260``` 261 262 263 264 265