harmony 鸿蒙UIExtensionComponent (系统接口)
UIExtensionComponent (系统接口)
UIExtensionComponent用于支持在本页面内嵌入其他应用提供的UI。展示的内容在另外一个进程中运行,本应用并不参与其中的布局和渲染。
通常用于有进程隔离诉求的模块化开发场景。
说明:
该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
本模块为系统接口。
使用约束
本组件不支持预览。
被拉起的Ability必须是带UI的Ability扩展,如何实现带UI的Ability扩展请参考实现带UI的Ability扩展。
必须显式设置组件宽高为非0有效值。
不支持滚动到边界后,传递至上层继续滚动的场景。当UIExtensionComponent组件使用方和扩展Ability都支持内容滚动时,通过手势滚动会导致UIExtensionComponent内外同时响应,包括但不限于Scroll、Swiper、List、Grid等滚动容器。内外手势同时滚动场景的规避方法可参考示例2。
子组件
无
接口
UIExtensionComponent(want: Want, options?: UIExtensionOptions)
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
want | Want | 是 | 要加载的Ability。 |
options11+ | UIExtensionOptions | 否 | 需要传递的构造项。 |
属性
支持通用属性。
事件
不支持点击等通用事件。
将事件经过坐标转换后传递给对端Ability处理。
支持以下事件:
onRemoteReady
onRemoteReady(callback: Callback<UIExtensionProxy>)
UIExtensionAbility连接完成时的回调,之后可使用proxy向被拉起的Ability发送数据。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |类型 |必填|说明 | |—————————-|——|————————————————————| |proxy |UIExtensionProxy|否|用于向对端Ability发送数据。 |
onReceive
onReceive(callback: ReceiveCallback)
收到被拉起的Ability发送的数据时触发的回调。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |类型 |必填|说明 | |—————————-|——|————————————————————| |data |ReceiveCallback|否|收到来自对端Ability的数据。 |
onResult(deprecated)
onResult(callback: Callback<{code: number; want?: Want}>)
被拉起的Ability扩展调用terminateSelfWithResult时会先触发本回调函数,再触发OnRelease。
本回调内可处理对端Ability的结果数据,可参考AbilityResult。
说明: 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用onTerminated替代。
参数:
参数名 | 类型 | 说明 |
---|---|---|
code | number | 收到来自对端Ability的处理结果code。 |
want | Want | 收到来自对端Ability的处理结果Want。 |
onRelease(deprecated)
onRelease(callback: Callback<number>)
用于处理被拉起的Ability销毁时的回调。
被拉起的Ability扩展调用terminateSelfWithResult或者terminateSelf时会触发本回调,此时releaseCode为0,即正常销毁。
被拉起的Ability扩展意外Crash或被kill时,触发本回调,此时releaseCode为1。
说明: 从 API version 10 开始支持,从 API version 12 开始废弃,建议使用onTerminated或者onError替代。
参数:
参数名 | 类型 | 说明 |
---|---|---|
releaseCode | number | 对端Ability销毁时的code,0为正常销毁,1为异常销毁。 |
onError
onError(callback:ErrorCallback)
被拉起的Ability扩展在运行过程中发生异常时触发本回调。可通过回调参数中的code、name和message获取错误信息并做处理,业务错误码详细介绍请参见UIExtension错误码。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |类型 |必填|说明 | |—————————-|——|————————————————————| |err |BusinessError|否|报错信息。 |
onTerminated12+
onTerminated(callback: Callback<TerminationInfo>)
被拉起的UIExtensionAbility通过调用terminateSelfWithResult
或者terminateSelf
正常退出时,触发本回调函数。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |类型 |必填|说明 | |——-|——|—————————————————————————————-| |callback|Callback<TerminationInfo>|否|回调函数,入参用于接收UIExtensionAbility的返回结果,类型为TerminationInfo。|
说明:
- 若UIExtensionAbility通过调用
terminateSelfWithResult
退出,其携带的信息会传给回调函数的入参。- 若UIExtensionAbility通过调用
terminateSelf
退出,上述回调函数的入参中,”code”取默认值”0”,”want”为”undefined”。
onDrawReady18+
onDrawReady(callback: Callback<void>)
被拉起的UIExtensionAbility绘制第一帧时触发本回调。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |类型 |必填|说明 | |—————————-|——|————————————————————| |callback |Callback <void>|否|回调函数,UIExtensionAbility绘制第一帧时触发本回调,类型为void。 |
TerminationInfo12+
用于表示被拉起的UIExtensionAbility通过调用terminateSelfWithResult
或者terminateSelf
正常退出时的返回结果。
属性名 | 类型 | 说明 |
---|---|---|
code | number | 被拉起UIExtensionAbility退出时返回的结果码。 |
want | Want | 被拉起UIExtensionAbility退出时返回的数据。 |
ReceiveCallback18+
type ReceiveCallback = Callback<Record<string, Object>>
用于封装被拉起的Ability发送的数据。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数: |参数名 |类型 |必填|说明 | |—————————-|——|————————————————————| |data |Record<string, Object>|否|收到来自对端Ability的数据。 |
UIExtensionOptions11+
用于在UIExtensionComponent进行构造的时传递可选的构造参数。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
isTransferringCaller | boolean | 否 | 在使用UIExtensionComponent嵌套时,设置当前UIExtensionComponent是否转发上一级的Caller信息。 默认值:false。 |
placeholder12+ | ComponentContent | 否 | 设置占位符,在UIExtensionComponent与UIExtensionAbility建立连接前显示。 |
dpiFollowStrategy12+ | DpiFollowStrategy | 否 | 提供接口支持设置DPI跟随宿主或跟随UIExtensionAbility。 默认值:FOLLOW_UI_EXTENSION_ABILITY_DPI。 |
areaChangePlaceholder14+ | Record |
否 | 设置尺寸变化占位符,在UIExtensionComponent尺寸发生变化并且UIExtension内部渲染未完成时显示, key值支持”FOLD_TO_EXPAND”(折叠展开尺寸变化)、”UNDEFINED”(默认尺寸变化)。 |
windowModeFollowStrategy18+ | WindowModeFollowStrategy | 否 | 提供接口以支持设置窗口Mode,使其能够跟随宿主或UIExtensionAbility。 默认值:FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE。 |
DpiFollowStrategy12+
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
名称 | 值 | 说明 |
---|---|---|
FOLLOW_HOST_DPI | 0 | 表示DPI跟随宿主。 |
FOLLOW_UI_EXTENSION_ABILITY_DPI | 1 | 表示DPI跟随UIExtensionAbility。 |
WindowModeFollowStrategy18+
窗口Mode跟随策略,用于设置窗口Mode,使其能够跟随宿主或UIExtensionAbility。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
名称 | 值 | 说明 |
---|---|---|
FOLLOW_HOST_WINDOW_MODE | 0 | 表示窗口Mode跟随宿主。 |
FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE | 1 | 表示窗口Mode跟随UIExtensionAbility。 |
UIExtensionProxy
用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据、订阅和取消订阅注册。
send
send(data: Record<string, Object>): void
用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供异步发送数据。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
data | Record<string, Object> | 是 | 异步发送给被拉起的扩展Ability的数据。 |
sendSync11+
sendSync(data: Record<string, Object>): Record<string, Object>
用于在双方建立连接成功后,组件使用方向被拉起的Ability发送数据的场景,提供同步发送数据。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
data | Record<string, Object> | 是 | 同步发送给被拉起的扩展Ability的数据。 |
返回值:
类型 | 描述 |
---|---|
Record<string, Object> | 扩展Ability回复的数据。 |
错误码:
以下错误码的详细介绍请参见UIExtension错误码。 |错误码ID|错误描述|说明| |——-|——–|——–| |100011|No callback has been registered to respond to this request.|扩展Ability未注册同步回调| |100012|Transferring data failed.|数据发送失败|
on(‘asyncReceiverRegister’)11+
on(type: ‘asyncReceiverRegister’, callback: Callback<UIExtensionProxy>): void
用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生异步注册的场景。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 代表订阅扩展Ability发生异步注册回调。 |
callback | Callback<UIExtensionProxy> | 是 | 订阅扩展Ability注册setReceiveDataCallback后触发的回调。 |
on(‘syncReceiverRegister’)11+
on(type: ‘syncReceiverRegister’, callback: Callback<UIExtensionProxy>): void;
用于在双方建立连接成功后,组件使用方订阅被拉起的Ability发生同步注册的场景。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 订阅扩展Ability发生同步注册回调。 |
callback | Callback<UIExtensionProxy> | 是 | 扩展Ability注册setReceiveDataForResultCallback后触发的回调。 |
off(‘asyncReceiverRegister’)11+
off(type: ‘asyncReceiverRegister’, callback?: Callback<UIExtensionProxy>): void
用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生异步注册的场景。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 取消订阅扩展Ability发生异步注册回调。 |
callback | Callback<UIExtensionProxy> | 否 | 为空代表取消订阅所有扩展Ability异步注册后触发回调。 非空代表取消订阅异步对应回调。 |
off(‘syncReceiverRegister’)11+
off(type: ‘syncReceiverRegister’, callback?: Callback<UIExtensionProxy>): void
用于在双方建立连接成功后,组件使用方取消订阅被拉起的Ability发生同步注册的场景。
系统接口: 此接口为系统接口。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 参数类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 取消订阅扩展Ability发生同步注册回调。 |
callback | Callback<UIExtensionProxy> | 否 | 为空代表取消订阅所有扩展Ability同步注册后触发回调 非空代表取消订阅同步对应回调。 |
示例
示例1 (加载UIExtension)
UIExtensionComponent组件使用分为使用方和提供方。本示例仅展示组件使用的方法和扩展的Ability,实际运行需在设备中安装bundleName为”com.example.newdemo”,abilityName为”UIExtensionProvider”的Ability扩展。
组件使用方
使用方入口界面Index.ets内容如下:
import { ComponentContent } from '@kit.ArkUI';
class Params {
}
@Builder
function LoadingBuilder(params: Params) {
Column() {
LoadingProgress()
.color(Color.Blue)
}
}
@Builder
function AreaChangePlaceholderBuilder(params: Params) {
Column() {
}
.width('100%')
.height('100%')
.backgroundColor(Color.Orange)
}
@Entry
@Component
struct Second {
@State message1: string = 'Hello World 1';
@State message2: string = 'Hello World 2';
@State message3: string = 'Hello World 3';
@State visible: Visibility = Visibility.Hidden;
@State wid: number = 300;
@State hei: number = 300;
@State windowStrategy: WindowModeFollowStrategy = WindowModeFollowStrategy.FOLLOW_UI_EXTENSION_ABILITY_WINDOW_MODE;
private proxy: UIExtensionProxy|null = null;
private initPlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(LoadingBuilder), new Params);
private areaChangePlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(AreaChangePlaceholderBuilder), new Params);
build() {
Row() {
Column() {
Text(this.message1).fontSize(30)
Text(this.message2).fontSize(30)
Text(this.message3).fontSize(30)
UIExtensionComponent({
bundleName : "com.example.newdemo",
abilityName: "UIExtensionProvider",
parameters: {
"ability.want.params.uiExtensionType": "sys/commonUI"
}},
{
placeholder: this.initPlaceholder,
areaChangePlaceholder: {
"FOLD_TO_EXPAND" : this.areaChangePlaceholder,
},
windowModeFollowStrategy: this.windowStrategy
})
.width(this.wid)
.height(this.hei)
.border({width: 5, color: Color.Blue})
.onReceive((data) => {
console.info('Lee onReceive, for test');
this.message3 = JSON.stringify(data['data']);
})
.onTerminated((info) => {
console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want));
})
.onRemoteReady((proxy) => {
console.info('onRemoteReady, for test');
this.proxy = proxy;
this.proxy.on("syncReceiverRegister", syncRegisterCallback1);
this.proxy.on("asyncReceiverRegister", (proxy1) => {
console.info("on invoke for test, type is asyncReceiverRegister");
});
})
Button("点击向UIExtensionAbility发送数据").onClick(() => {
if (this.proxy != undefined) {
this.proxy.send({data: "你好1"});
try {
let re = this.proxy.sendSync({data: "你好2"});
console.info("for test, re=" + JSON.stringify(re));
} catch (err) {
console.error(`sendSync failed for test. errCode=${err.code}, msg=${err.message}`);
}
}
})
}
.width('100%')
}
.height('100%')
}
}
function syncRegisterCallback1(proxy: UIExtensionProxy) {
console.info("on invoke for test, syncRegisterCallback1, type is syncReceiverRegister");
}
function syncRegisterCallback2(proxy: UIExtensionProxy) {
console.info("on invoke for test, syncRegisterCallback2, type is syncReceiverRegister");
}
组件提供方
提供方包含三个文件需要修改 - 提供方新增扩展入口文件/src/main/ets/uiextensionability/UIExtensionProvider.ets
import { UIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit';
const TAG: string = '[UIExtAbility]'
export default class UIExtAbility extends UIExtensionAbility {
onCreate() {
console.log(TAG, `UIExtAbility onCreate`);
}
onForeground() {
console.log(TAG, `UIExtAbility onForeground`);
}
onBackground() {
console.log(TAG, `UIExtAbility onBackground`);
}
onDestroy() {
console.log(TAG, `UIExtAbility onDestroy`);
}
onSessionCreate(want: Want, session: UIExtensionContentSession) {
console.log(TAG, `UIExtAbility onSessionCreate, want: ${JSON.stringify(want)}`);
let param: Record<string, UIExtensionContentSession> = {
'session': session
};
let storage: LocalStorage = new LocalStorage(param);
session.loadContent('pages/extension', storage);
}
onSessionDestroy(session: UIExtensionContentSession) {
console.log(TAG, `UIExtAbility onSessionDestroy`);
}
}
- 提供方扩展Ability入口页面文件/src/main/ets/pages/extension.ets “`ts import { UIExtensionContentSession } from ‘@kit.AbilityKit’;
let storage = new LocalStorage(); AppStorage.setOrCreate(‘message’, ‘UIExtensionAbility’);
@Entry(storage)
@Component
struct Extension {
@StorageLink(‘message’) storageLink: string = “;
private session: UIExtensionContentSession|undefined = storage.get
@Builder PageMap(name: string) { if (name === “hello”) { pageOneTmp(); } }
onPageShow() { if (this.session != undefined) { this.session.setReceiveDataCallback((data)=> { this.storageLink = JSON.stringify(data); console.info(“invoke for test, handle callback set by setReceiveDataCallback successfully”); })
this.session.setReceiveDataForResultCallback(func1);
}
}
build() { Navigation(this.pathStack) { Row() { Column() { Text(this.storageLink) .fontSize(20) .fontWeight(FontWeight.Bold) Button(“点击向Component发送数据”).onClick(()=>{ if (this.session != undefined) { this.session.sendData({“data”: 543321}); console.info(‘send 543321, for test’); } }) Button(“terminate”).onClick(()=> { if (this.session != undefined) { this.session.terminateSelf(); } storage.clear(); }) Button(“terminate with result”).onClick(()=>{ if (this.session != undefined) { this.session.terminateSelfWithResult({ resultCode: 0, want: { bundleName: “myBundleName”, parameters: { “result”: 123456 } } }); } storage.clear(); })
Button("点击跳转").onClick(()=> {
this.pathStack.pushPath({ name: "hello"});
})
}
}
.height('100%')
}.navDestination(this.PageMap)
.mode(NavigationMode.Stack)
} }
// pageOne @Component export struct pageOneTmp { pathStack: NavPathStack = new NavPathStack()
build() { NavDestination() { Column() { Text(“Hello World”) }.width(‘100%’).height(‘100%’) }.title(“pageOne”) .onBackPressed(() => { const popDestinationInfo = this.pathStack.pop(); // 弹出路由栈栈顶元素 console.log(‘pop’ + ‘返回值’ + JSON.stringify(popDestinationInfo)); return true; }) .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; }) } }
function func1(data: Record
- 提供方扩展Ability, module配置文件/src/main/module.json5添加对应配置
```json
{
"name": "UIExtensionProvider",
"srcEntry": "./ets/uiextensionability/UIExtensionProvider.ets",
"description": "1",
"label": "$string:EntryAbility_label",
"type": "sys/commonUI",
"exported": true,
}
示例2 (UEC内外部同时响应滚动时隔离处理)
本示例展示了当UIExtensionComponent组件使用方和扩展的Ability同时使用Scroll容器的场景,通过对UIExtensionComponent设置手势拦截处理,实现当UIExtensionComponent内部滚动时,外部组件不响应滚动。
手势使用方式: 组件内部滚动:手指在组件内部进行滚动操作; 组件外部滚动:拖动外部滚动条进行滚动。
实际运行时需先在设备中安装bundleName为”com.example.newdemo”,abilityName为”UIExtensionProvider”的Ability扩展。
提供方扩展入口文件UIExtensionProvider.ets与示例1扩展入口文件UIExtensionProvider.ets代码一致。
提供方扩展Ability, module配置文件与示例1扩展module配置文件module.json5代码一致。
- 使用方组件使用示例: “`ts @Entry @Component struct Second { @State message1: string = ‘Hello World 1’; @State message2: string = ‘Hello World 2’; @State message3: string = ‘Hello World 3’; @State visible: Visibility = Visibility.Hidden; @State wid: number = 300; @State hei: number = 300; private scroller: Scroller = new Scroller(); private arr: number[] = [0, 1, 2, 3, 4, 5, 6];
build() { Column() { // 可滚动的容器组件 Scroll(this.scroller) { Column() { Text(this.message1).fontSize(30) Text(this.message2).fontSize(30) Text(this.message3).fontSize(30)
// 重复设置组件,构造滚动内容
ForEach(this.arr, (item: number) => {
UIExtensionComponent({
bundleName: "com.example.newdemo",
abilityName: "UIExtensionProvider",
parameters: {
"ability.want.params.uiExtensionType": "sys/commonUI"
}
})
.width(this.wid)
.height(this.hei)
// 设置手势拦截,UEC外部组件不响应滚动
.gesture(PanGesture().onActionStart(() => {
console.info('UIExtensionComponent PanGesture onAction');
}))
.border({ width: 5, color: Color.Blue })
.onReceive((data) => {
console.info('Lee onReceive, for test');
this.message3 = JSON.stringify(data['data']);
})
.onTerminated((info) => {
console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want));
})
.onRemoteReady((proxy) => {
console.info('onRemoteReady, for test');
})
}, (item: string) => item)
}
.width('100%')
}
.scrollable(ScrollDirection.Vertical) // 滚动方向纵向
.scrollBar(BarState.On) // 滚动条常驻显示
.scrollBarColor(Color.Gray) // 滚动条颜色
.scrollBarWidth(10) // 滚动条宽度
.friction(0.6)
.edgeEffect(EdgeEffect.None)
.onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => {
console.info(xOffset + ' ' + yOffset);
})
.onScrollEdge((side: Edge) => {
console.info('To the edge');
})
.onScrollStop(() => {
console.info('Scroll Stop');
})
}
.height('100%')
} }
- 提供方扩展Ability入口页面文件extension.ets
```ts
@Entry
@Component
struct Extension {
@StorageLink('message') storageLink: string = '';
private scroller: Scroller = new Scroller();
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8];
build() {
Column() {
// 可滚动的容器组件
Scroll(this.scroller) {
Column() {
Text('Test demo')
.fontSize(20)
.fontWeight(FontWeight.Bold)
// 重复设置组件,构造滚动内容
ForEach(this.arr, (item: number) => {
Text(item.toString())
.width('90%')
.height(150)
.backgroundColor(Color.Pink)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
}, (item: string) => item)
}
}
}
.height('100%')
}
}
你可能感兴趣的鸿蒙文章
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦