场景动效类型互动卡片开发指导
本文档提供了场景动效类型互动卡片的开发指导,包括卡片非激活态和激活态UI界面开发、卡片配置文件开发。
接口说明
场景动效类型互动卡片关键接口如下表所示。
表1 主要接口
| 接口名 | 描述 |
|---|---|
| onLiveFormCreate(liveFormInfo: LiveFormInfo, session: UIExtensionContentSession): void | 互动卡片界面对象创建的回调函数。 |
| onLiveFormDestroy(liveFormInfo: LiveFormInfo): void | 互动卡片界面对象销毁、资源清理的回调函数。 |
| LiveFormExtensionContext | LiveFormExtensionAbility的上下文,继承自ExtensionContext。 |
| startAbilityByLiveForm(want: Want): Promise<void> | 拉起互动卡片提供方(应用)的页面。 |
| formProvider.requestOverflow(formId: string, overflowInfo: formInfo.OverflowInfo): Promise<void> | 卡片提供方发起互动卡片动效请求。 |
| formProvider.cancelOverflow(formId: string): Promise<void> | 卡片提供方发起取消互动卡片动效请求。 |
| formProvider.getFormRect(formId: string): Promise<formInfo.Rect> | 卡片提供方查询卡片位置、尺寸。 |
开发流程
卡片激活态UI开发
-
创建互动卡片
通过LiveFormExtensionAbility创建互动卡片,创建时加载互动卡片页面。
// entry/src/main/ets/myliveformextensionability/MyLiveFormExtensionAbility.etsimport { formInfo, LiveFormInfo, LiveFormExtensionAbility } from '@kit.FormKit';import { UIExtensionContentSession } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';const DOMAIN = 0x0000;export default class MyLiveFormExtensionAbility extends LiveFormExtensionAbility {onLiveFormCreate(liveFormInfo: LiveFormInfo, session: UIExtensionContentSession) {let storage: LocalStorage = new LocalStorage();storage.setOrCreate('context', this.context);storage.setOrCreate('session', session);let formId: string = liveFormInfo.formId;storage.setOrCreate('formId', formId);// 获取卡片圆角信息let borderRadius: number = liveFormInfo.borderRadius;storage.setOrCreate('borderRadius', borderRadius);// liveFormInfo.rect字段表示非激活态卡片组件相对激活态UI的位置和尺寸信息let formRect: formInfo.Rect = liveFormInfo.rect;storage.setOrCreate('formRect', formRect);hilog.info(DOMAIN, 'testTag', `MyLiveFormExtensionAbility onSessionCreate formId: ${formId}` +`, borderRadius: ${borderRadius}, formRectInfo: ${JSON.stringify(formRect)}`);// 加载互动页面session.loadContent('myliveformextensionability/pages/MyLiveFormPage', storage);}onLiveFormDestroy(liveFormInfo: LiveFormInfo) {hilog.info(DOMAIN, 'testTag', `MyLiveFormExtensionAbility onDestroy`);}}; -
实现互动卡片页面
// entry/src/main/ets/myliveformextensionability/pages/MyLiveFormPage.etsimport { formInfo, formProvider } from '@kit.FormKit';import { BusinessError } from '@kit.BasicServicesKit';import { common } from '@kit.AbilityKit';// Constants实现参考“互动卡片动效工具函数实现”小节import { Constants } from '../../common/Constants';import { hilog } from '@kit.PerformanceAnalysisKit';const ANIMATION_RECT_SIZE: number = 100;const END_SCALE: number = 1.5;const END_TRANSLATE: number = -300;const DOMAIN = 0x0000;@Entry@Componentstruct MyLiveFormPage {@State columnScale: number = 1.0;@State columnTranslate: number = 0.0;private uiContext: UIContext | undefined = undefined;private storageForMyLiveFormPage: LocalStorage | undefined = undefined;private formId: string | undefined = undefined;private formRect: formInfo.Rect | undefined = undefined;private formBorderRadius: number | undefined = undefined;private liveFormContext: common.LiveFormExtensionContext | undefined = undefined;aboutToAppear(): void {this.uiContext = this.getUIContext();if (!this.uiContext) {hilog.error(DOMAIN, 'testTag', 'no uiContext');return;}this.initParams();}private initParams(): void {this.storageForMyLiveFormPage = this.uiContext?.getSharedLocalStorage();this.formId = this.storageForMyLiveFormPage?.get<string>('formId');this.formRect = this.storageForMyLiveFormPage?.get<formInfo.Rect>('formRect');this.formBorderRadius = this.storageForMyLiveFormPage?.get<number>('borderRadius');this.liveFormContext = this.storageForMyLiveFormPage?.get<common.LiveFormExtensionContext>('context');}// 执行动效private runAnimation(): void {this.uiContext?.animateTo({duration: Constants.OVERFLOW_DURATION,curve: Curve.Ease}, () => {this.columnScale = END_SCALE;this.columnTranslate = END_TRANSLATE;});}private startAbilityByLiveForm(): void {try {// 请开发者替换为实际的want信息this.liveFormContext?.startAbilityByLiveForm({bundleName: 'com.samples.formlivedemo',abilityName: 'EntryAbility',}).then(() => {hilog.info(DOMAIN, 'testTag', 'startAbilityByLiveForm succeed');}).catch((err: BusinessError) => {hilog.error(DOMAIN, 'testTag',`startAbilityByLiveForm failed, code is ${err?.code}, message is ${err?.message}`);});} catch (e) {hilog.error(DOMAIN, 'testTag', `startAbilityByLiveForm failed, code is ${e?.code}, message is ${e?.message}`);}}build() {Stack({ alignContent: Alignment.TopStart }) {// 背景组件和普通卡片一样大Column().width(this.formRect ? this.formRect.width : 0).height(this.formRect ? this.formRect.height : 0).offset({x: this.formRect ? this.formRect.left : 0,y: this.formRect ? this.formRect.top : 0,}).borderRadius(this.formBorderRadius ? this.formBorderRadius : 0).backgroundColor('#2875F5')Stack() {this.buildContent();}.width('100%').height('100%')}.width('100%').height('100%').onClick(() => {hilog.info(DOMAIN, 'testTag', 'MyLiveFormPage click to start ability');if (!this.liveFormContext) {hilog.info(DOMAIN, 'testTag', 'MyLiveFormPage liveFormContext is empty');return;}this.startAbilityByLiveForm();})}@BuilderbuildContent() {Stack().width(ANIMATION_RECT_SIZE).height(ANIMATION_RECT_SIZE).backgroundColor(Color.White).scale({x: this.columnScale,y: this.columnScale,}).translate({y: this.columnTranslate}).onAppear(() => {// 在页面出现时执行动效this.runAnimation();})// $r('app.string.button_cancel')需要在相应的资源文件string.json中定义Button($r('app.string.button_cancel')).backgroundColor(Color.Grey).onClick(() => {if (!this.formId) {hilog.info(DOMAIN, 'testTag', 'MyLiveFormPage formId is empty, cancel overflow failed');return;}hilog.info(DOMAIN, 'testTag', 'MyLiveFormPage cancel overflow animation');formProvider.cancelOverflow(this.formId);})}} -
互动卡片LiveFormExtensionAbility配置
在module.json5配置文件中extensionAbilities标签下配置LiveFormExtensionAbility。
// entry/src/main/module.json5// ..."extensionAbilities": [// ...{"name": "MyLiveFormExtensionAbility","srcEntry": "./ets/myliveformextensionability/MyLiveFormExtensionAbility.ets","description": "MyLiveFormExtensionAbility","type": "liveForm"}],// ...在main_pages.json文件中声明互动卡片页面。
// entry/src/main/resources/base/profile/main_pages.json{"src": ["pages/Index","myliveformextensionability/pages/MyLiveFormPage"]}
卡片非激活态UI开发
-
非激活态卡片页面实现
非激活态卡片页面开发同普通卡片开发流程完全一致,在widgetCard.ets中完成。widgetCard.ets文件在卡片创建时自动生成,卡片创建流程可以参考创建ArkTS卡片。在非激活态卡片页面实现点击卡片时,发起卡片动效请求。
// entry/src/main/ets/widget/pages/WidgetCard.ets@Entry@Componentstruct WidgetCard {build() {Row() {Column() {// $r('app.string.liveform_click1')需要在相应的资源文件string.json中定义Text($r('app.string.liveform_click1'))// $r('app.float.font_size')需开发者根据实际情况替换相应的资源或值.fontSize($r('app.float.font_size')).fontWeight(FontWeight.Medium)// $r('sys.color.font_primary')需开发者根据实际情况替换相应的资源或值.fontColor($r('sys.color.font_primary'))}.width('100%')}.height('100%').onClick(() => {// 点击卡片时,选择向EntryFormAbility发送消息,并在其onFormEvent回调中调用formProvider.requestOverflow,请求卡片动效postCardAction(this, {action: 'message',abilityName: 'EntryFormAbility',params: {message: 'requestOverflow'}});})}} -
form_config.json配置
在form_config.json配置文件中新增sceneAnimationParams配置项。
// entry/src/main/resources/base/profile/form_config.json{"forms": [{"name": "widget","displayName": "$string:widget_display_name","description": "$string:widget_desc","src": "./ets/widget/pages/WidgetCard.ets","uiSyntax": "arkts","window": {"designWidth": 720,"autoDesignWidth": true},"colorMode": "auto","isDefault": true,"updateEnabled": true,"scheduledUpdateTime": "10:30","updateDuration": 1,"defaultDimension": "2*2","supportDimensions": ["2*2"],"formConfigAbility": "ability://EntryAbility","dataProxyEnabled": false,"isDynamic": true,"transparencyEnabled": false,"metadata": [],"sceneAnimationParams": {"abilityName": "MyLiveFormExtensionAbility"}}]}
互动卡片动效实现
-
触发互动卡片动效
互动卡片通过调用formProvider.requestOverflow接口触发动效,调用时需要明确:(1)动效申请范围。(2)动效持续时间。(3)是否使用系统提供的默认切换动效。具体可参考formInfo.OverflowInfo。其中,互动卡片可以通过调用formProvider.getFormRect接口获取卡片尺寸和在窗口内的位置信息。卡片提供方以此计算动效申请范围,单位为vp。计算规则具体请参考互动卡片请求参数约束。
// entry/src/main/ets/entryformability/EntryFormAbility.etsimport { FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';import { BusinessError } from '@kit.BasicServicesKit';// Constants实现参考“互动卡片动效工具函数实现”小节import { Constants } from '../common/Constants';import { hilog } from '@kit.PerformanceAnalysisKit';const TAG: string = 'EntryFormAbility';const DOMAIN_NUMBER: number = 0xFF00;export default class EntryFormAbility extends FormExtensionAbility {async onFormEvent(formId: string, message: string) {let shortMessage: string = JSON.parse(message)['message'];// 当接收的message为requestOverflow,触发互动卡片动效if (shortMessage === 'requestOverflow') {let formRect: formInfo.Rect = await formProvider.getFormRect(formId);this.requestOverflow(formId, formRect.width, formRect.height);return;}}private requestOverflow(formId: string, formWidth: number, formHeight: number): void {if (formWidth <= 0 || formHeight <= 0) {hilog.info(DOMAIN_NUMBER, TAG, 'requestOverflow failed, form size is not correct.');return;}// 基于卡片自身尺寸信息,计算卡片动效渲染区域let left: number = -Constants.OVERFLOW_LEFT_RATIO * formWidth;let top: number = -Constants.OVERFLOW_TOP_RATIO * formHeight;let width: number = Constants.OVERFLOW_WIDTH_RATIO * formWidth;let height: number = Constants.OVERFLOW_HEIGHT_RATIO * formHeight;let duration: number = Constants.OVERFLOW_DURATION;// 发起互动卡片动效申请try {formProvider.requestOverflow(formId, {// 动效申请范围area: {left: left,top: top,width: width,height: height},// 动效持续时间duration: duration,// 指定是否使用系统提供的默认切换动效useDefaultAnimation: true,}).then(() => {hilog.info(DOMAIN_NUMBER, TAG, 'requestOverflow requestOverflow succeed');}).catch((error: BusinessError) => {hilog.info(DOMAIN_NUMBER, TAG, `requestOverflow requestOverflow catch error` + `,code: ${error.code}, message: ${error.message}`);})} catch (e) {hilog.info(DOMAIN_NUMBER, TAG, `requestOverflow call requestOverflow catch error` + `,code: ${e.code}, message: ${e.message}`);}}} -
互动卡片动效工具函数实现
// entry/src/main/ets/common/Constants.ets// 动效相关常量的开发export class Constants {// 互动卡片动效超范围,左侧偏移百分比 = 偏移值/卡片宽度public static readonly OVERFLOW_LEFT_RATIO: number = 0.1;// 互动卡片动效超范围,上侧偏移百分比 = 偏移值/卡片高度public static readonly OVERFLOW_TOP_RATIO: number = 0.15;// 互动卡片动效超范围,宽度放大百分比public static readonly OVERFLOW_WIDTH_RATIO: number = 1.2;// 互动卡片动效超范围,高度放大百分比public static readonly OVERFLOW_HEIGHT_RATIO: number = 1.3;// 互动卡片动效超范围,动效时长public static readonly OVERFLOW_DURATION: number = 3500;} -
需要的资源文件string.json
{"string": [// ...{"name": "liveform_click1","value": "点击触发互动卡片动效"},{"name": "button_cancel","value": "强制取消动效"}]}
实现效果
以下是按照本文档代码示例开发而成的效果demo,demo执行动效时,点击按钮,将调用 formProvider.cancelOverflow 接口,打断当前破框动效,卡片切换为非激活态。
