• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&lt;TerminationInfo&gt;)
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