1# @ohos.arkui.UIContext (UIContext)(系统接口) 2 3在Stage模型中,WindowStage/Window可以通过loadContent接口加载页面并创建UI的实例,并将页面内容渲染到关联的窗口中,所以UI实例和窗口是一一关联的。一些全局的UI接口是和具体UI实例的执行上下文相关的,在当前接口调用时,通过追溯调用链跟踪到UI的上下文,来确定具体的UI实例。若在非UI页面中或者一些异步回调中调用这类接口,可能无法跟踪到当前UI的上下文,导致接口执行失败。 4 5> **说明:** 6> 7> 本模块首批接口从API version 10开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 8> 9> 示例效果请以真机运行为准,当前DevEco Studio预览器不支持。 10> 11> 当前页面仅包含本模块的系统接口,其他公开接口参见[@ohos.arkui.UIContext (UIContext)](arkts-apis-uicontext-uicontext.md)。 12 13## UIContext 14 15以下API需先使用ohos.window中的[getUIContext()](arkts-apis-window-Window.md#getuicontext10)方法获取UIContext实例,再通过此实例调用对应方法。或者可以通过自定义组件内置方法[getUIContext()](arkui-ts/ts-custom-component-api.md#getuicontext)获取。本文中UIContext对象以uiContext表示。 16 17### setDynamicDimming<sup>12+<sup> 18 19setDynamicDimming(id: string, value: number): void 20 21通过该方法设置组件的压暗程度。 22 23 24> **说明:** 25> 26> 设置该属性后设置其他效果类属性会导致效果冲突。 27 28**系统能力:** SystemCapability.ArkUI.ArkUI.Full 29 30**参数:** 31 32| 参数名 | 类型 | 必填 | 说明 | 33| ------- | ------- | ------- | ------- | 34| id | string | 是 | 组件id。 | 35| value | number | 是 | 组件压暗程度取值范围[0,1], 由0到1逐渐变亮。 | 36 37**示例:** 38 39```ts 40@Entry 41@Component 42struct Index { 43 @State 44 myCount : number = 100 45 46 build() { 47 Column(){ 48 Image($r('app.media.testImage')).width(500).height(800).id("test") 49 }.width("100%").height("100%").onClick(()=>{ 50 this.getUIContext().setDynamicDimming("test",1) 51 this.getUIContext()?.animateTo({duration:5000 },()=>{ 52 this.getUIContext().setDynamicDimming("test",0) 53 }) 54 }) 55 } 56} 57``` 58 59 60### animateToImmediately<sup>12+</sup> 61 62animateToImmediately(param: AnimateParam , event: () => void): void 63 64animateToImmediately接口允许用户通过UIContext对象,获取显式立即动画的能力。同时加载多个属性动画的情况下,使用该接口可以立即执行闭包代码中状态变化导致的过渡动效。 65 66**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 67 68**系统能力:** SystemCapability.ArkUI.ArkUI.Full 69 70**参数:** 71 72| 参数名 | 类型 | 必填 | 说明 | 73| ----- | ---------------------------------------- | ---- | ------------------------------------- | 74| param | [AnimateParam](arkui-ts/ts-explicit-animation.md#animateparam对象说明) | 是 | 设置动画效果相关参数。 | 75| event | () => void | 是 | 指定显示动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画。 | 76 77**示例:** 78 79该示例实现了通过UIContext对象获取显式立即动画的能力,调用animateToImmediately接口实现参数定义的动画效果。 80 81```ts 82// xxx.ets 83@Entry 84@Component 85struct AnimateToImmediatelyExample { 86 @State widthSize: number = 250 87 @State heightSize: number = 100 88 @State opacitySize: number = 0 89 private flag: boolean = true 90 uiContext: UIContext | null | undefined = this.getUIContext(); 91 92 build() { 93 Column() { 94 Column() 95 .width(this.widthSize) 96 .height(this.heightSize) 97 .backgroundColor(Color.Green) 98 .opacity(this.opacitySize) 99 Button('change size') 100 .margin(30) 101 .onClick(() => { 102 if (this.flag) { 103 this.uiContext?.animateToImmediately({ 104 delay: 0, 105 duration: 1000 106 }, () => { 107 this.opacitySize = 1 108 }) 109 this.uiContext?.animateTo({ 110 delay: 1000, 111 duration: 1000 112 }, () => { 113 this.widthSize = 150 114 this.heightSize = 60 115 }) 116 } else { 117 this.uiContext?.animateToImmediately({ 118 delay: 0, 119 duration: 1000 120 }, () => { 121 this.widthSize = 250 122 this.heightSize = 100 123 }) 124 this.uiContext?.animateTo({ 125 delay: 1000, 126 duration: 1000 127 }, () => { 128 this.opacitySize = 0 129 }) 130 } 131 this.flag = !this.flag 132 }) 133 }.width('100%').margin({ top: 5 }) 134 } 135} 136``` 137 138 139### freezeUINode<sup>18+</sup> 140 141freezeUINode(id: string, isFrozen: boolean): void 142 143通过id设置组件冻结状态,防止组件被标记为脏从而触发布局更新。 144 145**原子化服务API:** 从API version 18 开始,该接口支持在原子化服务中使用。 146 147**系统能力:** SystemCapability.ArkUI.ArkUI.Full 148 149**参数:** 150 151| 参数名 | 类型 | 必填 | 说明 | 152| --- | --- | --- | --- | 153| id | string | 是 | 组件的id。| 154| isFrozen | boolean | 是 | 是否设置冻结。<br/>true表示设置冻结,false表示设置不冻结。<br/>默认值为false。| 155 156**错误码:** 157 158以下错误码详情请参考[通用错误码](../errorcode-universal.md)。 159 160| 错误码ID | 错误信息 | 161| -------- | -------- | 162| 202 | The caller is not a system application. | 163 164```ts 165@Entry 166@Component 167struct Index { 168 @State columnWidth1: string = '100%'; 169 @State currentIndex: number = 0; 170 private controller: TabsController = new TabsController(); 171 172 build() { 173 Column() { 174 Tabs({ 175 barPosition: BarPosition.Start, 176 index: this.currentIndex, 177 controller: this.controller 178 }) { 179 TabContent() { 180 Column() 181 .width(this.columnWidth1) 182 .height('100%') 183 .backgroundColor('#00CB87') 184 } 185 .tabBar('green') 186 .id('tab1') 187 .onWillHide(() => { 188 // id为tab1的TabContent隐藏的时候设置该节点的冻结状态为true。 189 this.getUIContext().freezeUINode('tab1', true); 190 }) 191 .onWillShow(() => { 192 // id为tab1的TabContent显示的时候设置该节点的冻结状态为false。 193 this.getUIContext().freezeUINode('tab1', false); 194 }) 195 196 TabContent() { 197 Column() 198 .width('100%') 199 .height('100%') 200 .backgroundColor('#007DFF') 201 } 202 .tabBar('blue') 203 .id('tab2') 204 .onWillHide(() => { 205 // id为tab2的TabContent隐藏的时候设置该节点的冻结状态为true。 206 this.getUIContext().freezeUINode('tab2', true); 207 }) 208 .onWillShow(() => { 209 // 当id为tab2的TabContent显示的时候,将id为tab1的节点的冻结状态设置为true。 210 // 通过状态变量改变id为tab1的节点中Column的宽度。因该节点的冻结状态为true,标脏至TabContent时终止标记,不触发布局。 211 this.getUIContext().freezeUINode('tab1', true); 212 this.columnWidth1 = '50%'; 213 // 配置延时任务。 214 setTimeout(() => { 215 // 将id为tab1的节点的冻结状态设置为false,重新触发标记和布局。 216 this.getUIContext().freezeUINode('tab1', false); 217 // 通过状态变量更新tab1内部Column节点的宽度,设置this.columnWidth1为'20%'。 218 this.columnWidth1 = '20%'; 219 }, 5000) 220 }) 221 222 TabContent() { 223 Column() 224 .width('100%') 225 .height('100%') 226 .backgroundColor('#FFBF00') 227 } 228 .tabBar('yellow') 229 .id('tab3') 230 .onWillHide(() => { 231 // 当id为tab3的TabContent隐藏的时候设置该节点的冻结状态为true。 232 this.getUIContext().freezeUINode('tab3', true); 233 }) 234 .onWillShow(() => { 235 // id为tab3的TabContent显示的时候设置该节点的冻结状态为false。 236 this.getUIContext().freezeUINode('tab3', false); 237 }) 238 239 } 240 .vertical(false) 241 .barMode(BarMode.Fixed) 242 .barWidth(360) 243 .barHeight(56) 244 .animationDuration(0) 245 .onChange((index: number) => { 246 this.currentIndex = index; 247 }) 248 .width(360) 249 .height(296) 250 .margin({ top: 52 }) 251 .backgroundColor('#F1F3F5') 252 }.width('100%') 253 } 254} 255``` 256 257### freezeUINode<sup>18+</sup> 258 259freezeUINode(uniqueId: number, isFrozen: boolean): void 260 261通过uniqueId设置组件的冻结状态,防止组件被标记为脏从而触发布局更新。 262 263**原子化服务API:** 从API version 18 开始,该接口支持在原子化服务中使用。 264 265**系统能力:** SystemCapability.ArkUI.ArkUI.Full 266 267**参数:** 268 269| 参数名 | 类型 | 必填 | 说明 | 270| --- | --- | --- | --- | 271| uniqueId | number | 是 | 组件的uniqueId。| 272| isFrozen | boolean | 是 | 是否设置冻结。<br/>true表示设置冻结,false表示设置不冻结。<br/>默认值为false。| 273 274**错误码:** 275 276以下错误码详细介绍请参考[通用错误码](../errorcode-universal.md)。 277 278| 错误码ID | 错误信息 | 279| -------- | -------- | 280| 202 | The caller is not a system application. | 281 282```ts 283@Entry 284@Component 285struct Index { 286 @State columnWidth1: string = '100%'; 287 @State currentIndex: number = 0; 288 private controller: TabsController = new TabsController(); 289 290 build() { 291 Column() { 292 Tabs({ 293 barPosition: BarPosition.Start, 294 index: this.currentIndex, 295 controller: this.controller 296 }) { 297 TabContent() { 298 Column() 299 .width(this.columnWidth1) 300 .height('100%') 301 .backgroundColor('#00CB87') 302 } 303 .tabBar('green') 304 .id('tab1') 305 .onWillHide(() => { 306 // 通过id查询以获取对应节点的uniqueId。 307 const node = this.getUIContext().getFrameNodeById('tab1'); 308 const uniqueId = node?.getUniqueId(); 309 // 当id为tab1的TabContent隐藏的时候,通过uniqueId设置该节点的冻结状态为true。 310 this.getUIContext().freezeUINode(uniqueId, true); 311 }) 312 .onWillShow(() => { 313 // 通过id查询以获取对应节点的uniqueId。 314 const node = this.getUIContext().getFrameNodeById('tab1'); 315 const uniqueId = node?.getUniqueId(); 316 // 当id为tab1的TabContent显示的时候,通过uniqueId设置该节点的冻结状态为false。 317 this.getUIContext().freezeUINode(uniqueId, false) 318 }) 319 320 TabContent() { 321 Column() 322 .width('100%') 323 .height('100%') 324 .backgroundColor('#007DFF') 325 } 326 .tabBar('blue') 327 .id('tab2') 328 .onWillHide(() => { 329 // 通过id查询以获取对应节点的uniqueId。 330 const node = this.getUIContext().getFrameNodeById('tab2'); 331 const uniqueId = node?.getUniqueId(); 332 // 当id为tab2的TabContent隐藏的时候,通过uniqueId设置该节点的冻结状态为true。 333 this.getUIContext().freezeUINode(uniqueId, true); 334 }) 335 .onWillShow(() => { 336 // 通过id查询以获取对应节点的uniqueId。 337 const node = this.getUIContext().getFrameNodeById('tab1'); 338 const uniqueId = node?.getUniqueId(); 339 // 当id为tab2的TabContent显示的时候,通过uniqueId设置id为tab1的节点的冻结状态为true。 340 // 通过状态变量改变id为tab1的节点内部Column节点的宽度。由于id为tab1的节点冻结状态为true,标脏至该TabContent时会终止标记,并且不会从该节点开始触发布局。 341 this.getUIContext().freezeUINode(uniqueId, true); 342 this.columnWidth1 = '50%'; 343 344 // 设置延时任务。 345 setTimeout(() => { 346 // 将id为tab1的节点的冻结状态设置为false,以重新触发标记和布局。 347 this.getUIContext().freezeUINode(uniqueId, false); 348 this.columnWidth1 = '20%'; 349 }, 5000) 350 }) 351 352 TabContent() { 353 Column() 354 .width('100%') 355 .height('100%') 356 .backgroundColor('#FFBF00') 357 } 358 .tabBar('yellow') 359 .id('tab3') 360 .onWillHide(() => { 361 // 通过id查询以获取对应节点的uniqueId。 362 const node = this.getUIContext().getFrameNodeById('tab3'); 363 const uniqueId = node?.getUniqueId(); 364 // 当id为tab3的TabContent隐藏时,通过uniqueId将该节点的冻结状态设置为true。 365 this.getUIContext().freezeUINode(uniqueId, true); 366 }) 367 .onWillShow(() => { 368 // 通过id查询以获取对应节点的uniqueId。 369 const node = this.getUIContext().getFrameNodeById('tab3'); 370 const uniqueId = node?.getUniqueId(); 371 // 当id为tab3的TabContent显示的时候,通过uniqueId设置该节点的冻结状态为false。 372 this.getUIContext().freezeUINode(uniqueId, false); 373 }) 374 375 } 376 .vertical(false) 377 .barMode(BarMode.Fixed) 378 .barWidth(360) 379 .barHeight(56) 380 .animationDuration(0) 381 .onChange((index: number) => { 382 this.currentIndex = index; 383 }) 384 .width(360) 385 .height(296) 386 .margin({ top: 52 }) 387 .backgroundColor('#F1F3F5') 388 }.width('100%') 389 } 390} 391``` 392 393### setKeyboardAppearanceConfig<sup>20+</sup> 394 395setKeyboardAppearanceConfig(uniqueId: number, config: KeyboardAppearanceConfig): void 396 397设置键盘样式,包括模糊效果和流光效果,仅在沉浸式模式下生效,沉浸式定义可参见[KeyboardAppearance枚举说明](../apis-arkui/arkui-ts/ts-text-common.md#keyboardappearance15枚举说明)。其中,流光效果依赖于模糊效果,若需启用流光效果,则需同时开启模糊效果,最终显示效果取决于输入法处理。 398 399**系统接口:** 此接口为系统接口。 400 401**系统能力:** SystemCapability.ArkUI.ArkUI.Full 402 403**参数:** 404 405| 参数名 | 类型 | 必填 | 说明 | 406| --- | --- | --- | --- | 407| uniqueId | number | 是 | 组件节点对应的UniqueId。取值范围大于等于0。 | 408| config | [KeyboardAppearanceConfig](../apis-arkui/arkui-ts/ts-text-common-sys.md#keyboardappearanceconfig20) | 是 | 键盘样式配置参数。| 409 410**错误码:** 411 412以下错误码详细介绍请参考[通用错误码](../errorcode-universal.md)。 413 414| 错误码ID | 错误信息 | 415| -------- | -------- | 416| 202 | The caller is not a system application. | 417 418输入框和搜索框组件设置键盘样式使用示例: 419 420```ts 421@Entry 422@Component 423struct IMEGradient { 424 textInputController: TextInputController = new TextInputController(); 425 searchController: SearchController = new SearchController(); 426 427 build() { 428 Column() { 429 TextInput({ controller: this.textInputController}) 430 .margin(10) 431 .border({ width: 1 }) 432 .onWillAttachIME((client) => { 433 this.getUIContext().setKeyboardAppearanceConfig(client.nodeId, 434 { 435 gradientMode: KeyboardGradientMode.LINEAR_GRADIENT, 436 fluidLightMode: KeyboardFluidLightMode.BACKGROUND_FLUID_LIGHT 437 }) 438 }) 439 .keyboardAppearance(KeyboardAppearance.IMMERSIVE) 440 441 Search({ controller: this.searchController }) 442 .margin(10) 443 .border({ width: 1 }) 444 .onWillAttachIME((client) => { 445 this.getUIContext().setKeyboardAppearanceConfig(client.nodeId, 446 { 447 gradientMode: KeyboardGradientMode.LINEAR_GRADIENT, 448 fluidLightMode: KeyboardFluidLightMode.BACKGROUND_FLUID_LIGHT 449 }) 450 }) 451 .keyboardAppearance(KeyboardAppearance.IMMERSIVE) 452 }.width('100%').height('100%').justifyContent(FlexAlign.Center) 453 } 454} 455``` 456 457## ComponentSnapshot<sup>12+</sup> 458 459以下API需先使用UIContext中的[getComponentSnapshot()](arkts-apis-uicontext-uicontext.md#getcomponentsnapshot12)方法获取ComponentSnapshot对象,再通过此实例调用对应方法。 460 461缩放、平移、旋转等图形变换属性只对被截图组件的子组件生效;对目标组件本身应用图形变换属性不生效,显示的是还是图形变换前的效果。 462 463### getWithRange<sup>20+</sup> 464getWithRange(start: NodeIdentity, end: NodeIdentity, isStartRect: boolean, options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap>; 465 466传入两个组件的ID,获取范围内的组件的截图,并通过Promise返回结果。 467 468> **说明:** 469> 470> start对应的组件和end对应的组件必须为同一棵组件树上的组件,且start对应的组件需要为end对应的组件的祖先组件。 471 472**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 473 474**系统能力:** SystemCapability.ArkUI.ArkUI.Full 475 476**参数:** 477 478| 参数名 | 类型 | 必填 | 说明 | 479| ---- | ------ | ---- | ------- | 480| start | [NodeIdentity](arkts-apis-uicontext-t.md#nodeidentity20) | 是 | 范围开始的组件的ID。 | 481| end | [NodeIdentity](arkts-apis-uicontext-t.md#nodeidentity20) | 是 | 范围结束的组件的ID。 | 482| isStartRect | boolean | 是 | 范围是否以开始组件的外接矩形为准。<br/>true表示以开始组件的外接矩形为准,false表示以结束组件的外接矩形为准。<br/>默认值为true。 | 483| options | [componentSnapshot.SnapshotOptions](js-apis-arkui-componentSnapshot.md#snapshotoptions12) | 否 | 截图相关的自定义参数,不支持region参数。 | 484 485**返回值:** 486 487| 类型 | 说明 | 488| -------- | -------- | 489| image.[PixelMap](../apis-image-kit/arkts-apis-image-PixelMap.md) | 截图返回的结果。 | 490 491**错误码:** 492 493以下错误码的详细介绍请参见[通用错误码](../errorcode-universal.md)错误码和[截图错误码](errorcode-snapshot.md)。 494 495| 错误码ID | 错误信息 | 496| ------ | ------- | 497| 202 | The caller is not a system application. | 498| 100001 | Invalid ID. | 499 500**示例:** 501 502```ts 503import { image } from '@kit.ImageKit'; 504 505@Entry 506@Component 507struct SnapshotExample { 508 @State pixmap: image.PixelMap | undefined = undefined 509 build() { 510 Column() { 511 Row() { 512 Row() { 513 Row() { 514 Column() { 515 Text('Text1').id('text1') 516 Text('Text2').id('text2') 517 Row() { 518 Text('Text3').id('text3') 519 }.id('root5').backgroundColor('#E4E8F0') 520 }.width('80%').height('80%').justifyContent(FlexAlign.SpaceAround).backgroundColor('#C1D1F0').id('root4') 521 }.width('80%').height('80%').justifyContent(FlexAlign.Center).backgroundColor('#FFEEF0').id('root3') 522 .backgroundBlurStyle(BlurStyle.Thin, { colorMode: ThemeColorMode.LIGHT }) 523 }.width('80%').height('80%').justifyContent(FlexAlign.Center).backgroundColor('#D5D5D5').id('root2') 524 }.width('50%').height('50%').justifyContent(FlexAlign.Center).backgroundColor('#E4E8F0').id('root1') 525 Row() { 526 Button("getWithRange") 527 .onClick(() => { 528 this.getUIContext().getComponentSnapshot().getWithRange('root2', 'root4', true) 529 .then((pixmap: image.PixelMap) => { 530 this.pixmap = pixmap 531 }).catch((err:Error) => { 532 console.error("error: " + err) 533 }) 534 }).margin(10) 535 }.justifyContent(FlexAlign.SpaceAround) 536 Row() { 537 Image(this.pixmap).width(200).height(300).border({ color: Color.Black, width: 2 }).margin(5) 538 }.justifyContent(FlexAlign.SpaceAround) 539 } 540 .id('root') 541 .width('100%') 542 .height('100%') 543 .alignItems(HorizontalAlign.Center) 544 } 545} 546``` 547 548 549