1# UIExtensionComponent (系统接口) 2 3UIExtensionComponent用于支持在本页面内嵌入其他应用提供的UI。展示的内容在另外一个进程中运行,本应用并不参与其中的布局和渲染。 4 5通常用于有进程隔离诉求的模块化开发场景。 6 7> **说明:** 8> 9> 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 10> 11> 本模块为系统接口。 12 13## 使用约束 14 15本组件不支持预览。 16 17被拉起的Ability必须是带UI的Ability扩展,如何实现带UI的Ability扩展请参考[实现带UI的Ability扩展](../../apis-ability-kit/js-apis-app-ability-uiExtensionAbility.md)。 18 19必须显式设置组件宽高为非0有效值。 20 21不支持滚动到边界后,传递至上层继续滚动的场景。当UIExtensionComponent组件使用方和扩展Ability都支持内容滚动时,通过手势滚动会导致UIExtensionComponent内外同时响应,包括但不限于[Scroll](ts-container-scroll.md)、[Swiper](ts-container-swiper.md)、[List](ts-container-list.md)、[Grid](ts-container-grid.md)等滚动容器。内外手势同时滚动场景的规避方法可参考[示例2](#示例2-uec内外部同时响应滚动时隔离处理)。 22 23 24## 子组件 25 26无 27 28## 接口 29 30UIExtensionComponent(want: Want, options?: UIExtensionOptions) 31 32**参数:** 33 34| 参数名 | 参数类型 | 必填 | 参数描述 | 35| --------------------- | ---------------------------------------------------------- | ---- | ------------------ | 36| want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) | 是 | 要加载的Ability。 | 37| options<sup>11+</sup> | [UIExtensionOptions](#uiextensionoptions11) | 否 | 需要传递的构造项。 | 38 39## 属性 40 41支持[通用属性](ts-component-general-attributes.md)。 42 43## 事件 44 45不支持[点击](ts-universal-events-click.md)等通用事件。 46 47将事件经过坐标转换后传递给对端Ability处理。 48 49支持以下事件: 50 51### onRemoteReady 52 53onRemoteReady(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<UIExtensionProxy>) 54 55UIExtensionAbility连接完成时的回调,之后可使用proxy向被拉起的Ability发送数据。 56 57**参数:** 58 59| 参数名 | 类型 | 说明 | 60| ---------------------------- | ------ | ------------------------------------------------------------ | 61| proxy | UIExtensionProxy | 用于向对端Ability发送数据。 | 62 63### onReceive 64 65onReceive(callback: ReceiveCallback) 66 67收到被拉起的Ability发送的数据时触发的回调。 68 69**参数:** 70 71| 参数名 | 类型 | 说明 | 72| ---------------------------- | ------ | ------------------------------------------------------------ | 73| data | [ReceiveCallback](#receivecallback18) | 收到来自对端Ability的数据。 | 74 75### onResult<sup>(deprecated)</sup> 76 77onResult(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<{code: number; want?: Want}>) 78 79被拉起的Ability扩展调用terminateSelfWithResult时会先触发本回调函数,再触发OnRelease。 80 81本回调内可处理对端Ability的结果数据,可参考[AbilityResult](../../apis-ability-kit/js-apis-inner-ability-abilityResult.md)。 82 83> **说明:** 84> 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用[onTerminated](#onterminated12)替代。 85 86**参数:** 87 88| 参数名 | 类型 | 说明 | 89| ---------------------------- | ------ | ------------------------------------------------------------ | 90| code | number | 收到来自对端Ability的处理結果code。 | 91| want | Want | 收到来自对端Ability的处理結果[Want](../../apis-ability-kit/js-apis-app-ability-want.md)。 | 92 93### onRelease<sup>(deprecated)</sup> 94 95onRelease(callback: [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<number>) 96 97用于处理被拉起的Ability销毁时的回调。 98 99被拉起的Ability扩展调用terminateSelfWithResult或者terminateSelf时会触发本回调,此时releaseCode为0,即正常销毁。 100 101被拉起的Ability扩展意外Crash或被kill时,触发本回调,此时releaseCode为1。 102 103> **说明:** 104> 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用[onTerminated](#onterminated12)或者[onError](#onerror)替代。 105 106**参数:** 107 108| 参数名 | 类型 | 说明 | 109| ---------------------------- | ------ | ------------------------------------------------------------ | 110| releaseCode | number | 对端Ability销毁时的code,0为正常销毁,1为异常销毁。 | 111 112### onError 113 114onError(callback:[ErrorCallback](../../apis-basic-services-kit/js-apis-base.md#errorcallback)) 115 116被拉起的Ability扩展在运行过程中发生异常时触发本回调。可通过回调参数中的code、name和message获取错误信息并做处理。 117 118**参数:** 119 120| 参数名 | 类型 | 说明 | 121| ---------------------------- | ------ | ------------------------------------------------------------ | 122| err | [BusinessError](../../apis-basic-services-kit/js-apis-base.md#businesserror) | 报错信息。 | 123 124### onTerminated<sup>12+<sup> 125 126onTerminated(callback: Callback<TerminationInfo>) 127 128被拉起的UIExtensionAbility通过调用`terminateSelfWithResult`或者`terminateSelf`正常退出时,触发本回调函数。 129 130**参数:** 131 132| 参数名 | 类型 | 说明 | 133| ------- | ------ | ---------------------------------------------------------------------------------------- | 134| callback | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback)\<[TerminationInfo](#terminationinfo12)> | 回调函数,入参用于接收UIExtensionAbility的返回结果,类型为[TerminationInfo](#terminationinfo12)。 | 135 136> **说明:** 137> 138> - 若UIExtensionAbility通过调用`terminateSelfWithResult`退出,其携带的信息会传给回调函数的入参。 139> - 若UIExtensionAbility通过调用`terminateSelf`退出,上述回调函数的入参中,"code"取默认值"0","want"为"undefined"。 140 141### onDrawReady<sup>18+<sup> 142 143onDrawReady(callback: Callback\<void>) 144 145被拉起的UIExtensionAbility绘制第一帧时触发本回调。 146 147**参数:** 148 149| 参数名 | 类型 | 说明 | 150| ---------------------------- | ------ | ------------------------------------------------------------ | 151| callback | [Callback](../../apis-basic-services-kit/js-apis-base.md#callback) \<void> | 回调函数,UIExtensionAbility绘制第一帧时触发本回调,类型为void。 | 152 153### TerminationInfo<sup>12+<sup> 154 155用于表示被拉起的UIExtensionAbility通过调用`terminateSelfWithResult`或者`terminateSelf`正常退出时的返回结果。 156 157| 属性名 | 类型 | 说明 | 158| ------- | ------ | --------------------------------------------------- | 159| code | number | 被拉起UIExtensionAbility退出时返回的结果码。 | 160| want | [Want](../../apis-ability-kit/js-apis-app-ability-want.md) | 被拉起UIExtensionAbility退出时返回的数据。 | 161 162## ReceiveCallback<sup>18+<sup> 163type ReceiveCallback = Callback\<Record\<string, Object\>\> 164 165用于封装被拉起的Ability发送的数据。 166 167**系统能力:** SystemCapability.ArkUI.ArkUI.Full 168 169**参数:** 170| 参数名 | 类型 | 说明 | 171| ---------------------------- | ------ | ------------------------------------------------------------ | 172| data | Record\<string, Object\> | 收到来自对端Ability的数据。 | 173 174## UIExtensionOptions<sup>11+</sup> 175用于在UIExtensionComponent进行构造的时传递可选的构造参数。 176 177**参数:** 178 179| 参数名 | 参数类型 | 必填 | 参数描述 | 180| ---- | ---------------------------------------- | ---- | --------------- | 181| isTransferringCaller | boolean | 否 | 在使用UIExtensionComponent嵌套时,设置当前UIExtensionComponent是否转发上一级的Caller信息。</br> 默认值:false。 | 182| placeholder<sup>12+<sup> | [ComponentContent](../js-apis-arkui-ComponentContent.md) | 否 | 设置占位符,在UIExtensionComponent与UIExtensionAbility建立连接前显示。 | 183| dpiFollowStrategy<sup>12+<sup> | [DpiFollowStrategy](ts-container-ui-extension-component-sys.md#dpifollowstrategy12) | 否 | 提供接口支持设置DPI跟随宿主或跟随UIExtensionAbility。</br> 默认值:FOLLOW_UI_EXTENSION_ABILITY_DPI。 | 184| areaChangePlaceholder<sup>14+<sup> | Record<string, [ComponentContent](../js-apis-arkui-ComponentContent.md)> | 否 | 设置尺寸变化占位符,在UIExtensionComponent尺寸发生变化并且UIExtension内部渲染未完成时显示, key值支持"FOLD_TO_EXPAND"(折叠展开尺寸变化)、"UNDEFINED"(默认尺寸变化)。 | 185| windowModeFollowStrategy<sup>18+<sup> | [WindowModeFollowStrategy](ts-container-ui-extension-component-sys.md#windowmodefollowstrategy18) | 否 | 提供接口以支持设置窗口Mode,使其能够跟随宿主或UIExtensionAbility。</br> 默认值:FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE。 | 186 187## DpiFollowStrategy<sup>12+</sup> 188 189| 名称 | 描述 | 190| -------------------------------- | --------------- | 191| FOLLOW_HOST_DPI | 表示DPI跟随宿主。 | 192| FOLLOW_UI_EXTENSION_ABILITY_DPI | 表示DPI跟随UIExtensionAbility。 | 193 194## WindowModeFollowStrategy<sup>18+</sup> 195 196窗口Mode跟随策略,用于设置窗口Mode,使其能够跟随宿主或UIExtensionAbility。 197 198| 名称 | 值 | 描述 | 199| ---------------------------------------- | ----|--------------- | 200| FOLLOW_HOST_WINDOW_MODE | 0 | 表示窗口Mode跟随宿主。 | 201| FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE | 1 | 表示窗口Mode跟随UIExtensionAbility。 | 202 203## UIExtensionProxy 204 205用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据、订阅和取消订阅注册。 206 207### send 208 209send(data: Record\<string, Object\>): void 210 211用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供异步发送数据。 212 213**系统能力:** SystemCapability.ArkUI.ArkUI.Full 214 215**参数:** 216 217| 参数名 | 参数类型 | 必填 | 参数描述 | 218| ---- | ---------------------------------------- | ---- | --------------- | 219| data | Record\<string, Object\> | 是 | 异步发送给被拉起的扩展Ability的数据。 | 220 221### sendSync<sup>11+</sup> 222 223sendSync(data: Record\<string, Object\>): Record\<string, Object\> 224 225用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供同步发送数据。 226 227**系统能力:** SystemCapability.ArkUI.ArkUI.Full 228 229**参数:** 230 231| 参数名 | 参数类型 | 必填 | 参数描述 | 232| ---- | ---------------------------------------- | ---- | --------------- | 233| data | Record\<string, Object\> | 是 | 同步发送给被拉起的扩展Ability的数据。 | 234 235**返回值:** 236 237| 类型 | 描述 | 238| ---- | ----| 239| Record\<string, Object\> | 扩展Ability回复的数据。 | 240 241**错误码:** 242 243| 错误号 | 描述 | 244| ---- | ----| 245| 100011 | 扩展Ability未注册同步回调 | 246| 100012 | 数据发送失败 | 247 248### on('asyncReceiverRegister')<sup>11+</sup> 249 250on(type: 'asyncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void 251 252用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生异步注册的场景。 253 254**系统能力:** SystemCapability.ArkUI.ArkUI.Full 255 256**参数:** 257 258| 参数名 | 参数类型 |必填 | 参数描述 | 259| ------ | -------- |---- | ------- | 260| type | string | 是 | 代表订阅扩展Ability发生异步注册回调。 | 261| callback | Callback\<UIExtensionProxy\> | 是 | 订阅扩展Ability注册setReceiveDataCallback后触发的回调。 | 262 263### on('syncReceiverRegister')<sup>11+</sup> 264 265on(type: 'syncReceiverRegister', callback: Callback\<UIExtensionProxy\>): void; 266 267用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生同步注册的场景。 268 269**系统能力:** SystemCapability.ArkUI.ArkUI.Full 270 271**参数:** 272 273| 参数名 | 参数类型 |必填 | 参数描述 | 274| ------ | -------- |---- | ------- | 275| type | string | 是 | 订阅扩展Ability发生同步注册回调。 | 276| callback | Callback\<UIExtensionProxy\> | 是 | 扩展Ability注册setReceiveDataForResultCallback后触发的回调。 | 277 278### off('asyncReceiverRegister')<sup>11+</sup> 279 280off(type: 'asyncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void 281 282用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生异步注册的场景。 283 284**系统能力:** SystemCapability.ArkUI.ArkUI.Full 285 286**参数:** 287 288| 参数名 | 参数类型 | 必填 | 参数描述 | 289| ------ | -------- | ----- | ------- | 290| type | string | 是 | 取消订阅扩展Ability发生异步注册回调。 | 291| callback | Callback\<UIExtensionProxy\> | 否 | 为空代表取消订阅所有扩展Ability异步注册后触发回调。<br> 非空代表取消订阅异步对应回调。 | 292 293### off('syncReceiverRegister')<sup>11+</sup> 294 295off(type: 'syncReceiverRegister', callback?: Callback\<UIExtensionProxy\>): void 296 297用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生同步注册的场景。 298 299**系统能力:** SystemCapability.ArkUI.ArkUI.Full 300 301**参数:** 302 303| 参数名 | 参数类型 | 必填 | 参数描述 | 304| ------ | -------- | ----- | ------- | 305| type | string | 是 | 取消订阅扩展Ability发生同步注册回调。 | 306| callback | Callback\<UIExtensionProxy\> | 否 | 为空代表取消订阅所有扩展Ability同步注册后触发回调<br> 非空代表取消订阅同步对应回调。 | 307 308## 示例 309 310### 示例1 (加载UIExtension) 311 312UIExtensionComponent组件使用分为使用方和提供方。本示例仅展示组件使用的方法和扩展的Ability,实际运行需在设备中安装bundleName为"com.example.newdemo",abilityName为"UIExtensionProvider"的Ability扩展。 313 314**组件使用方** 315 316使用方入口界面Index.ets内容如下: 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("点击向UIExtensionAbility发送数据").onClick(() => { 392 if (this.proxy != undefined) { 393 this.proxy.send({data: "你好1"}) 394 395 try { 396 let re = this.proxy.sendSync({data: "你好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**组件提供方** 419 420提供方包含三个文件需要修改 421- 提供方新增扩展入口文件/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- 提供方扩展Ability入口页面文件/src/main/ets/pages/extension.ets 460```ts 461import { UIExtensionContentSession } from '@kit.AbilityKit'; 462 463let storage = new LocalStorage() 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("点击向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("点击跳转").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() // 弹出路由栈栈顶元素 547 console.log('pop' + '返回值' + 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- 提供方扩展Ability, module配置文件/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### 示例2 (UEC内外部同时响应滚动时隔离处理) 578 579本示例展示了当UIExtensionComponent组件使用方和扩展的Ability同时使用[Scroll](ts-container-scroll.md)容器的场景,通过对UIExtensionComponent设置手势拦截处理,实现当UIExtensionComponent内部滚动时,外部组件不响应滚动。 580 581手势使用方式: 582组件内部滚动:手指在组件内部进行滚动操作; 583组件外部滚动:拖动外部滚动条进行滚动。 584 585实际运行时需先在设备中安装bundleName为"com.example.newdemo",abilityName为"UIExtensionProvider"的Ability扩展。 586 587提供方扩展入口文件UIExtensionProvider.ets与[示例1](#示例1-加载uiextension)扩展入口文件UIExtensionProvider.ets代码一致。 588 589提供方扩展Ability, module配置文件与[示例1](#示例1-加载uiextension)扩展module配置文件module.json5代码一致。 590 591- 使用方组件使用示例: 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 // 可滚动的容器组件 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 // 重复设置组件,构造滚动内容 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 // 设置手势拦截,UEC外部组件不响应滚动 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) // 滚动方向纵向 645 .scrollBar(BarState.On) // 滚动条常驻显示 646 .scrollBarColor(Color.Gray) // 滚动条颜色 647 .scrollBarWidth(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- 提供方扩展Ability入口页面文件extension.ets 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 // 可滚动的容器组件 677 Scroll(this.scroller) { 678 Column() { 679 Text('Test demo') 680 .fontSize(20) 681 .fontWeight(FontWeight.Bold) 682 // 重复设置组件,构造滚动内容 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