1# UIExtensionComponent (System API) 2 3**UIExtensionComponent** is used to embed UIs provided by other applications in the local application UI. The embedded content runs in another process, and the local application does not participate in its layout and rendering. 4 5This component is usually used in modular development scenarios where process isolation is required. 6 7> **NOTE** 8> 9> This component is supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version. 10> 11> The APIs provided by this component are system APIs. 12 13## Restrictions 14 15This component does not support preview. 16 17The ability to be started must be a UIExtensionAbility, an extension ability with UI. For details about how to implement a UIExtensionAbility, see [@ohos.app.ability.UIExtensionAbility (Base Class for ExtensionAbilities with UI)](../../apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md). 18 19The width and height of the component must be explicitly set to non-zero valid values. 20 21Scrolling to the boundary and then passing the scroll gesture to the upper layer is not supported. When both the UIExtensionComponent and the UIExtensionAbility support content scrolling, using gestures to scroll can cause simultaneous responses inside and outside the **UIExtensionComponent**. This includes but is not limited to scrolling containers such as [Scroll](ts-container-scroll.md), [Swiper](ts-container-swiper.md), [List](ts-container-list.md), and [Grid](ts-container-grid.md). For details about how to avoid the simultaneous scrolling inside and outside the **UIExtensionComponent**, see [Example 2](#example-2-isolating-scrolling-in-uiextensioncomponent-and-external-components. 22 23 24## Child Components 25 26Not supported 27 28## APIs 29 30UIExtensionComponent(want: Want, options?: UIExtensionOptions) 31 32**Parameters** 33 34| Name | Type | Mandatory| Description | 35| --------------------- | ---------------------------------------------------------- | ---- | ------------------ | 36| want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) | Yes | Ability to start. | 37| options<sup>11+</sup> | [UIExtensionOptions](#uiextensionoptions11) | No | Construction parameters to be transferred.| 38 39## Attributes 40 41The [universal attributes](ts-component-general-attributes.md) are supported. 42 43## Events 44 45Universal events, such as the [click event](ts-universal-events-click.md), are not supported. 46 47The events are passed to the remote UIExtensionAbility for processing after coordinate conversion. 48 49The following events are supported: 50 51### onRemoteReady 52 53onRemoteReady(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<UIExtensionProxy>) 54 55Invoked when the connection to the remote UIExtensionAbility is set up, that is, the UIExtensionAbility is ready to receive data through the proxy. 56 57**Parameters** 58 59| Name | Type | Description | 60| ---------------------------- | ------ | ------------------------------------------------------------ | 61| proxy | UIExtensionProxy | Proxy used to send data to the remote UIExtensionAbility. | 62 63### onReceive 64 65onReceive(callback: ReceiveCallback) 66 67Invoked when the data sent by the started UIExtensionAbility is received. 68 69**Parameters** 70 71| Name | Type | Description | 72| ---------------------------- | ------ | ------------------------------------------------------------ | 73| data | [ReceiveCallback](#receivecallback18) | Data from the remote UIExtensionAbility. | 74 75### onResult<sup>(deprecated)</sup> 76 77onResult(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<{code: number; want?: Want}>) 78 79Invoked when the started UIExtensionAbility calls **terminateSelfWithResult**. After this callback is invoked, **OnRelease** is invoked. 80 81The result data of the remote UIExtensionAbility can be processed in this callback. For details, see [AbilityResult](../../apis-ability-kit/js-apis-inner-ability-abilityResult.md). 82 83> **NOTE** 84> This API is supported since API version 10 and deprecated since API version 12. You are advised to use [onTerminated](#onterminated12) instead. 85 86**Parameters** 87 88| Name | Type | Description | 89| ---------------------------- | ------ | ------------------------------------------------------------ | 90| code | number | Result code from the remote UIExtensionAbility. | 91| want | Want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) of the result from the remote UIExtensionAbility.| 92 93### onRelease<sup>(deprecated)</sup> 94 95onRelease(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number>) 96 97Invoked when the started UIExtensionAbility is destroyed. 98 99If the UIExtensionAbility is destroyed correctly by calling **terminateSelfWithResult** or **terminateSelf**, the value of **releaseCode** is **0**. 100 101If the UIExtensionAbility is destroyed because it crashes or is forced stopped, the value of **releaseCode** is **1**. 102 103> **NOTE** 104> This API is supported since API version 10 and deprecated since API version 12. You are advised to use [onTerminated](#onterminated12) or [onError](#onerror) instead. 105 106**Parameters** 107 108| Name | Type | Description | 109| ---------------------------- | ------ | ------------------------------------------------------------ | 110| releaseCode | number | Code that indicates how the remote UIExtensionAbility is destroyed. The value **0** means normal destruction, and **1** means abnormal destruction. | 111 112### onError 113 114onError(callback:[ErrorCallback](../../apis-basic-services-kit/js-apis-base.md#errorcallback)) 115 116Invoked when an exception occurs during the running of the UIExtensionAbility. You can obtain the error information based on the **code**, **name**, and **message** parameters in the callback and rectify the exception accordingly. 117 118**Parameters** 119 120| Name | Type | Description | 121| ---------------------------- | ------ | ------------------------------------------------------------ | 122| err | [BusinessError](../../apis-basic-services-kit/js-apis-base.md#businesserror) | Error information. | 123 124### onTerminated<sup>12+<sup> 125 126onTerminated(callback: Callback<TerminationInfo>) 127 128Called when the started UIExtensionAbility is terminated by calling **terminateSelfWithResult** or **terminateSelf**. 129 130**Parameters** 131 132| Name | Type | Description | 133| ------- | ------ | ---------------------------------------------------------------------------------------- | 134| callback | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<[TerminationInfo](#terminationinfo12)> | Callback used to return the result from the UIExtensionAbility.| 135 136> **NOTE** 137> 138> - If the UIExtensionAbility is terminated by calling **terminateSelfWithResult**, the carried information is passed as arguments into the callback function. 139> - If the UIExtensionAbility is terminated by calling **terminateSelf**, the input parameters **code** and **want** in the callback function are at their default values: **0** and **undefined**, respectively. 140 141### onDrawReady<sup>18+<sup> 142 143onDrawReady(callback: Callback\<void>) 144 145Called when the UIExtensionAbility draws its first frame. 146 147**Parameters** 148 149| Name | Type | Description | 150| ---------------------------- | ------ | ------------------------------------------------------------ | 151| callback | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback) \<void> | Callback triggered when the first frame of the UIExtensionAbility is drawn. | 152 153### TerminationInfo<sup>12+<sup> 154 155Represents the result returned when the UIExtensionAbility that has been started exits properly by calling **terminateSelfWithResult** or **terminateSelf**. 156 157| Name | Type | Description | 158| ------- | ------ | --------------------------------------------------- | 159| code | number | Result code returned when the UIExtensionAbility exits.| 160| want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) | Data returned when the UIExtensionAbility exits. | 161 162## ReceiveCallback<sup>18+<sup> 163type ReceiveCallback = Callback\<Record\<string, Object\>\> 164 165Defines the object used to encapsulate the data sent by the launched ability. 166 167**System capability**: SystemCapability.ArkUI.ArkUI.Full 168 169**Parameters** 170| Name | Type | Description | 171| ---------------------------- | ------ | ------------------------------------------------------------ | 172| data | Record\<string, Object\> | Data from the remote UIExtensionAbility. | 173 174## UIExtensionOptions<sup>11+</sup> 175Describes the optional construction parameters during **UIExtensionComponent** construction. 176 177**Parameters** 178 179| Name | Type | Mandatory| Description | 180| ---- | ---------------------------------------- | ---- | --------------- | 181| isTransferringCaller | boolean | No | Whether the UIExtensionComponent forwards the upper-level caller information when it is used for nesting.<br> Default value: **false**| 182| placeholder<sup>12+<sup> | [ComponentContent](../js-apis-arkui-ComponentContent.md) | No | Placeholder to be displayed before the UIExtensionComponent establishes a connection with the UIExtensionAbility.| 183| dpiFollowStrategy<sup>12+<sup> | [DpiFollowStrategy](ts-container-ui-extension-component-sys.md#dpifollowstrategy12) | No | Whether the DPI settings follow the host or UIExtensionAbility.<br> Default value: **FOLLOW_UI_EXTENSION_ABILITY_DPI**.| 184| areaChangePlaceholder<sup>14+<sup> | Record<string, [ComponentContent](../js-apis-arkui-ComponentContent.md)> | No | Placeholders for size changes, displayed when the UIExtensionComponent's size changes and the internal rendering of the UIExtension is not completed. The key values support **"FOLD_TO_EXPAND"** (size change for folding and expanding) and **"UNDEFINED"** (default size change).| 185| windowModeFollowStrategy<sup>18+<sup> | [WindowModeFollowStrategy](ts-container-ui-extension-component-sys.md#windowmodefollowstrategy18) | No | Following strategy of the window mode.<br> Default value: **FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE**.| 186 187## DpiFollowStrategy<sup>12+</sup> 188 189| Name | Description | 190| -------------------------------- | --------------- | 191| FOLLOW_HOST_DPI | The DPI settings follow the host.| 192| FOLLOW_UI_EXTENSION_ABILITY_DPI | The DPI settings follow the UIExtensionAbility.| 193 194## WindowModeFollowStrategy<sup>18+</sup> 195 196Enumerates the following strategies of the window mode. 197 198| Name | Value | Description | 199| ---------------------------------------- | ----|--------------- | 200| FOLLOW_HOST_WINDOW_MODE | 0 | The window mode follows the host.| 201| FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE | 1 | The window mode follows the UIExtensionAbility.| 202 203## UIExtensionProxy 204 205Implements a **UIExtensionProxy** instance for the component host to send data to, subscribe to, or unsubscribe from the started UIExtensionAbility through the connection established between the two parties. 206 207### send 208 209send(data: Record\<string, Object\>): void 210 211Asynchronously sends data from the component host to the started UIExtensionAbility through the connection established between the two parties. 212 213**System capability**: SystemCapability.ArkUI.ArkUI.Full 214 215**Parameters** 216 217| Name | Type | Mandatory | Description | 218| ---- | ---------------------------------------- | ---- | --------------- | 219| data | Record\<string, Object\> | Yes | Data to be asynchronously sent to the started UIExtensionAbility.| 220 221### sendSync<sup>11+</sup> 222 223sendSync(data: Record\<string, Object\>): Record\<string, Object\> 224 225Synchronously sends data from the component host to the started UIExtensionAbility through the connection established between the two parties. 226 227**System capability**: SystemCapability.ArkUI.ArkUI.Full 228 229**Parameters** 230 231| Name | Type | Mandatory | Description | 232| ---- | ---------------------------------------- | ---- | --------------- | 233| data | Record\<string, Object\> | Yes | Data to be synchronously sent to the started UIExtensionAbility.| 234 235**Return value** 236 237| Type| Description| 238| ---- | ----| 239| Record\<string, Object\> | Data returned by the UIExtensionAbility.| 240 241**Error codes** 242 243| ID| Description| 244| ---- | ----| 245| 100011 | UIExtensionAbility not registered.| 246| 100012 | Failed to send data.| 247 248### on('asyncReceiverRegister')<sup>11+</sup> 249 250on(type: 'asyncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void 251 252Subscribes to asynchronous registration of the started UIExtensionAbility through the connection established between the component host and UIExtensionAbility. 253 254**System capability**: SystemCapability.ArkUI.ArkUI.Full 255 256**Parameters** 257 258| Name | Type|Mandatory| Description| 259| ------ | -------- |---- | ------- | 260| type | string | Yes| Event type. The value is fixed at **'asyncReceiverRegister'**.| 261| callback | Callback\<UIExtensionProxy\> | Yes| Callback used to return the result.| 262 263### on('syncReceiverRegister')<sup>11+</sup> 264 265on(type: 'syncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void; 266 267Subscribes to synchronous registration of the started UIExtensionAbility through the connection established between the component host and UIExtensionAbility. 268 269**System capability**: SystemCapability.ArkUI.ArkUI.Full 270 271**Parameters** 272 273| Name | Type|Mandatory| Description| 274| ------ | -------- |---- | ------- | 275| type | string | Yes| Event type. The value is fixed at **'syncReceiverRegister'**.| 276| callback | Callback\<UIExtensionProxy\> | Yes| Callback used to return the result.| 277 278### off('asyncReceiverRegister')<sup>11+</sup> 279 280off(type: 'asyncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void 281 282Unsubscribes from asynchronous registration of the started UIExtensionAbility through the connection established between the component host and UIExtensionAbility. 283 284**System capability**: SystemCapability.ArkUI.ArkUI.Full 285 286**Parameters** 287 288| Name | Type| Mandatory| Description| 289| ------ | -------- | ----- | ------- | 290| type | string | Yes| Event type. The value is fixed at **'asyncReceiverRegister'**.| 291| callback | Callback\<UIExtensionProxy\> | No| Callback used for unsubscription.<br> If this parameter is not set, this API unsubscribes from all callbacks corresponding to **type**.| 292 293### off('syncReceiverRegister')<sup>11+</sup> 294 295off(type: 'syncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void 296 297Unsubscribes from synchronous registration of the started UIExtensionAbility through the connection established between the component host and UIExtensionAbility. 298 299**System capability**: SystemCapability.ArkUI.ArkUI.Full 300 301**Parameters** 302 303| Name | Type| Mandatory| Description| 304| ------ | -------- | ----- | ------- | 305| type | string | Yes| Event type. The value is fixed at **'syncReceiverRegister'**.| 306| callback | Callback\<UIExtensionProxy\> | No| Callback used for unsubscription.<br> If this parameter is not set, this API unsubscribes from all callbacks corresponding to **type**.| 307 308## Example 309 310### Example 1: Loading a UIExtension 311 312The use of the **UIExtensionComponent** is divided into the user side and the provider side. This example shows only the method used by the component and the UIExtensionAbility. For the code to run properly, you need to install the ability whose **bundleName** is **"com.example.newdemo"** and **abilityName** is **"UIExtensionProvider"** on the device. 313 314**User Side** 315 316The entry point file **Index.ets** for the user side is as follows: 317```ts 318import { ComponentContent } from '@kit.ArkUI'; 319class Params { 320} 321@Builder 322function LoadingBuilder(params: Params) { 323 Column() { 324 LoadingProgress() 325 .color(Color.Blue) 326 } 327} 328@Builder 329function AreaChangePlaceholderBuilder(params: Params) { 330 Column() { 331 } 332 .width('100%') 333 .height('100%') 334 .backgroundColor(Color.Orange) 335} 336@Entry 337@Component 338struct Second { 339 @State message1: string = 'Hello World 1' 340 @State message2: string = 'Hello World 2' 341 @State message3: string = 'Hello World 3' 342 @State visible: Visibility = Visibility.Hidden 343 @State wid: number = 300 344 @State hei: number = 300 345 @State windowStrategy: WindowModeFollowStrategy = WindowModeFollowStrategy.FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE; 346 private proxy: UIExtensionProxy | null = null; 347 private initPlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(LoadingBuilder), new Params); 348 private areaChangePlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(AreaChangePlaceholderBuilder), new Params); 349 350 351 build() { 352 Row() { 353 Column() { 354 Text(this.message1).fontSize(30) 355 Text(this.message2).fontSize(30) 356 Text(this.message3).fontSize(30) 357 UIExtensionComponent({ 358 bundleName : "com.example.newdemo", 359 abilityName: "UIExtensionProvider", 360 parameters: { 361 "ability.want.params.uiExtensionType": "sys/commonUI" 362 }}, 363 { 364 placeholder: this.initPlaceholder, 365 areaChangePlaceholder: { 366 "FOLD_TO_EXPAND" : this.areaChangePlaceholder, 367 }, 368 windowModeFollowStrategy: this.windowStrategy 369 }) 370 .width(this.wid) 371 .height(this.hei) 372 .border({width: 5, color: Color.Blue}) 373 .onReceive((data) => { 374 console.info('Lee onReceive, for test') 375 this.message3 = JSON.stringify(data['data']) 376 }) 377 .onTerminated((info) => { 378 console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want)); 379 }) 380 .onRemoteReady((proxy) => { 381 console.info('onRemoteReady, for test') 382 this.proxy = proxy 383 384 this.proxy.on("syncReceiverRegister", syncRegisterCallback1); 385 386 this.proxy.on("asyncReceiverRegister", (proxy1) => { 387 console.info("on invoke for test, type is asyncReceiverRegister"); 388 }); 389 }) 390 391 Button("Send to UIExtensionAbility").onClick(() => { 392 if (this.proxy != undefined) { 393 this.proxy.send({data: "Hello 1"}) 394 395 try { 396 let re = this.proxy.sendSync({data: "Hello 2"}) 397 console.info("for test, re=" + JSON.stringify(re)); 398 } catch (err) { 399 console.error(`sendSync failed for test. errCode=${err.code}, msg=${err.message}`); 400 } 401 } 402 }) 403 } 404 .width('100%') 405 } 406 .height('100%') 407 } 408} 409 410function syncRegisterCallback1(proxy: UIExtensionProxy) { 411 console.info("on invoke for test, syncRegisterCallback1, type is syncReceiverRegister"); 412} 413 414function syncRegisterCallback2(proxy: UIExtensionProxy) { 415 console.info("on invoke for test, syncRegisterCallback2, type is syncReceiverRegister"); 416} 417``` 418**Provider Side** 419 420Perform the following: 421- Add the extension entry point file: **/src/main/ets/uiextensionability/UIExtensionProvider.ets**. 422```ts 423import { UIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit'; 424 425const TAG: string = '[UIExtAbility]' 426export default class UIExtAbility extends UIExtensionAbility { 427 428 onCreate() { 429 console.log(TAG, `UIExtAbility onCreate`) 430 } 431 432 onForeground() { 433 console.log(TAG, `UIExtAbility onForeground`) 434 } 435 436 onBackground() { 437 console.log(TAG, `UIExtAbility onBackground`) 438 } 439 440 onDestroy() { 441 console.log(TAG, `UIExtAbility onDestroy`) 442 } 443 444 onSessionCreate(want: Want, session: UIExtensionContentSession) { 445 console.log(TAG, `UIExtAbility onSessionCreate, want: ${JSON.stringify(want)}`) 446 let param: Record<string, UIExtensionContentSession> = { 447 'session': session 448 }; 449 let storage: LocalStorage = new LocalStorage(param); 450 session.loadContent('pages/extension', storage); 451 } 452 453 onSessionDestroy(session: UIExtensionContentSession) { 454 console.log(TAG, `UIExtAbility onSessionDestroy`) 455 } 456} 457``` 458 459- Modify the extension ability entry page file: **/src/main/ets/pages/extension.ets** 460```ts 461import { UIExtensionContentSession } from '@kit.AbilityKit'; 462 463let storage = LocalStorage.getShared() 464AppStorage.setOrCreate('message', 'UIExtensionAbility') 465 466@Entry(storage) 467@Component 468struct Extension { 469 @StorageLink('message') storageLink: string = ''; 470 private session: UIExtensionContentSession | undefined = storage.get<UIExtensionContentSession>('session'); 471 pathStack: NavPathStack = new NavPathStack() 472 473 @Builder 474 PageMap(name: string) { 475 if (name === "hello") { 476 pageOneTmp() 477 } 478 } 479 480 onPageShow() { 481 if (this.session != undefined) { 482 this.session.setReceiveDataCallback((data)=> { 483 this.storageLink = JSON.stringify(data) 484 console.info("invoke for test, handle callback set by setReceiveDataCallback successfully"); 485 }) 486 487 this.session.setReceiveDataForResultCallback(func1) 488 } 489 } 490 491 build() { 492 Navigation(this.pathStack) { 493 Row() { 494 Column() { 495 Text(this.storageLink) 496 .fontSize(20) 497 .fontWeight(FontWeight.Bold) 498 Button("Send to Component").onClick(()=>{ 499 if (this.session != undefined) { 500 this.session.sendData({"data": 543321}) 501 console.info('send 543321, for test') 502 } 503 }) 504 Button("terminate").onClick(()=> { 505 if (this.session != undefined) { 506 this.session.terminateSelf(); 507 } 508 storage.clear() 509 }) 510 Button("terminate with result").onClick(()=>{ 511 if (this.session != undefined) { 512 this.session.terminateSelfWithResult({ 513 resultCode: 0, 514 want: { 515 bundleName: "myBundleName", 516 parameters: { "result": 123456 } 517 } 518 }) 519 } 520 storage.clear() 521 }) 522 523 Button("Redirect").onClick(()=> { 524 this.pathStack.pushPath({ name: "hello"}) 525 }) 526 } 527 } 528 .height('100%') 529 }.navDestination(this.PageMap) 530 .mode(NavigationMode.Stack) 531 } 532} 533 534// pageOne 535@Component 536export struct pageOneTmp { 537 pathStack: NavPathStack = new NavPathStack() 538 539 build() { 540 NavDestination() { 541 Column() { 542 Text("Hello World") 543 }.width('100%').height('100%') 544 }.title("pageOne") 545 .onBackPressed(() => { 546 const popDestinationInfo = this.pathStack.pop() // Pop the top element out of the navigation stack. 547 console.log('pop' + 'Return value' + JSON.stringify(popDestinationInfo)) 548 return true 549 }) 550 .onReady((context: NavDestinationContext) => { 551 this.pathStack = context.pathStack 552 }) 553 } 554} 555 556function func1(data: Record<string, Object>): Record<string, Object> { 557 let linkToMsg: SubscribedAbstractProperty<string> = AppStorage.link('message'); 558 linkToMsg.set(JSON.stringify(data)) 559 console.info("invoke for test, handle callback set by setReceiveDataForResultCallback successfully"); 560 return data; 561} 562 563``` 564 565- Modify the extension ability module configuration file: **/src/main/module.json5**. 566```json 567{ 568 "name": "UIExtensionProvider", 569 "srcEntry": "./ets/uiextensionability/UIExtensionProvider.ets", 570 "description": "1", 571 "label": "$string:EntryAbility_label", 572 "type": "sys/commonUI", 573 "exported": true, 574} 575``` 576 577### Example 2: Isolating Scrolling in UIExtensionComponent and External Components 578 579This example demonstrates how to handle simultaneous scrolling in both the UIExtensionComponent and the external container. When both the UIExtensionComponent and the external container use the [Scroll](ts-container-scroll.md) container, you can isolate the scrolling behavior by intercepting gestures on the UIExtensionComponent. This ensures that when the user scrolls inside the UIExtensionComponent, the external container does not respond to the scroll gesture. 580 581Gesture handling: 582Internal scrolling: scrolling within the component using touch gestures 583External scrolling: scrolling of the outer container using the scrollbar 584 585For the code to run properly, you need to install the ability whose **bundleName** is **"com.example.newdemo"** and **abilityName** is **"UIExtensionProvider"** on the device. 586 587The provider side remains the same as in [Example 1](#example-1-loading-a-uiextension). 588 589The entry point file **UIExtensionProvider.ets** and the module configuration file** module.json5** are identical to those in [Example 1](#example-1-loading-a-uiextension). 590 591- Provider side implementation: 592```ts 593@Entry 594@Component 595struct Second { 596 @State message1: string = 'Hello World 1' 597 @State message2: string = 'Hello World 2' 598 @State message3: string = 'Hello World 3' 599 @State visible: Visibility = Visibility.Hidden 600 @State wid: number = 300 601 @State hei: number = 300 602 private scroller: Scroller = new Scroller(); 603 private arr: number[] = [0, 1, 2, 3, 4, 5, 6] 604 605 build() { 606 Column() { 607 // Scrollable container component. 608 Scroll(this.scroller) { 609 Column() { 610 Text(this.message1).fontSize(30) 611 Text(this.message2).fontSize(30) 612 Text(this.message3).fontSize(30) 613 614 // Repeat components to create scrollable content. 615 ForEach(this.arr, (item: number) => { 616 UIExtensionComponent({ 617 bundleName: "com.example.newdemo", 618 abilityName: "UIExtensionProvider", 619 parameters: { 620 "ability.want.params.uiExtensionType": "sys/commonUI" 621 } 622 }) 623 .width(this.wid) 624 .height(this.hei) 625 // Use gesture interception to prevent external components from responding to scrolling. 626 .gesture(PanGesture().onActionStart(() => { 627 console.info('UIExtensionComponent PanGesture onAction') 628 })) 629 .border({ width: 5, color: Color.Blue }) 630 .onReceive((data) => { 631 console.info('Lee onReceive, for test') 632 this.message3 = JSON.stringify(data['data']) 633 }) 634 .onTerminated((info) => { 635 console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want)); 636 }) 637 .onRemoteReady((proxy) => { 638 console.info('onRemoteReady, for test') 639 }) 640 }, (item: string) => item) 641 } 642 .width('100%') 643 } 644 .scrollable(ScrollDirection.Vertical) // The scrollbar scrolls in the vertical direction. 645 .scrollBar(BarState.On) // The scrollbar is always displayed. 646 .scrollBarColor(Color.Gray) // The scrollbar color is gray. 647 .scrollBarWidth(10) // The scrollbar width is 10. 648 .friction(0.6) 649 .edgeEffect(EdgeEffect.None) 650 .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => { 651 console.info(xOffset + ' ' + yOffset) 652 }) 653 .onScrollEdge((side: Edge) => { 654 console.info('To the edge') 655 }) 656 .onScrollStop(() => { 657 console.info('Scroll Stop') 658 }) 659 } 660 .height('100%') 661 } 662} 663``` 664 665- Entry file **extension.ets** for the provider side: 666```ts 667@Entry 668@Component 669struct Extension { 670 @StorageLink('message') storageLink: string = ''; 671 private scroller: Scroller = new Scroller(); 672 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8] 673 674 build() { 675 Column() { 676 // Scrollable container component. 677 Scroll(this.scroller) { 678 Column() { 679 Text('Test demo') 680 .fontSize(20) 681 .fontWeight(FontWeight.Bold) 682 // Repeat components to create scrollable content. 683 ForEach(this.arr, (item: number) => { 684 Text(item.toString()) 685 .width('90%') 686 .height(150) 687 .backgroundColor(Color.Pink) 688 .borderRadius(15) 689 .fontSize(16) 690 .textAlign(TextAlign.Center) 691 .margin({ top: 10 }) 692 }, (item: string) => item) 693 } 694 } 695 696 } 697 .height('100%') 698 } 699} 700``` 701