博客 / 詳情

返回

HarmonyOS場景動效互動卡片開發實戰:打造“破框”動態交互體驗

在HarmonyOS應用開發中,互動卡片是提升用户體驗的重要載體,而場景動效類型互動卡片更是憑藉“破框”動效、狀態靈活切換等特性,為用户帶來更具沉浸感的交互體驗。本文將基於HarmonyOS官方開發指南,結合DevEco Studio 6.0開發環境,通過完整技術案例,詳細講解場景動效互動卡片的開發流程、核心接口、配置要點及動效實現,幫助開發者快速落地此類功能。

一、案例核心目標

本次開發實現一款場景動效互動卡片,具備以下核心功能:

  1. 支持非激活態與激活態切換:非激活態展示基礎UI,點擊後切換至激活態執行“破框”動效(縮放+平移);
  2. 動效可控:提供“強制取消動效”按鈕,支持手動中斷動效並返回非激活態;
  3. 符合系統約束:嚴格遵循動效時長、渲染區域、功耗控制等系統規範。

二、開發環境準備

  • 開發工具:DevEco Studio 6.0
  • HarmonyOS SDK:API Version 10+(DevEco Studio 6.0默認安裝基礎SDK為API 12,已滿足10+要求,若需適配更低10/11版本可手動補充下載)
  • 測試設備:支持場景動效卡片的華為機型(如Mate 60系列、Mate 70系列、Pura 70系列等)
  • 環境配置注意:DevEco Studio 6.0需開啓“HarmonyOS互動卡片開發”插件,路徑為:Settings → Plugins → 搜索“HarmonyOS LiveForm Plugin” → 安裝並重啓IDE;因IDE默認SDK為API 12,若項目需指定API 10/11開發,需在Project Structure中手動調整Module的Compile SDK Version。

三、核心開發流程

(一)項目結構規劃

基於DevEco Studio 6.0創建HarmonyOS應用項目(選擇“Empty Ability”模板),完成後補充場景動效卡片相關目錄,最終項目結構如下:

entry/
├─ src/main/ets/
│ ├─ common/
│ │ └─ Constants.ets // 動效常量配置
│ ├─ entryformability/
│ │ └─ EntryFormAbility.ets // 卡片事件處理(接收動效請求)
│ ├─ myliveformextensionability/
│ │ ├─ MyLiveFormExtensionAbility.ets // 激活態核心擴展能力
│ │ └─ pages/
│ │ └─ MyLiveFormPage.ets // 激活態UI及動效實現頁面
│ └─ widget/
│ └─ pages/
│ └─ WidgetCard.ets // 非激活態基礎UI頁面
├─ src/main/resources/base/profile/
│ ├─ form_config.json // 卡片基礎配置(關聯動效能力)
│ └─ main_pages.json // 激活態頁面註冊
└─ src/main/module.json5 // 應用擴展能力聲明(LiveForm類型)

(二)基礎配置:常量與核心配置文件

場景動效卡片的正常運行依賴4類核心配置,需嚴格按照API 10及以上規範配置(DevEco Studio 6.0默認API 12可直接兼容),避免因配置缺失導致動效無法觸發。

  1. 動效常量定義(Constants.ets)

統一管理動效偏移比例、放大比例、時長等參數,便於後續維護調整,同時符合系統對動效時長的約束(最大3500ms):

// 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; // 上側偏移比例
// 動效放大比例(控制“破框”範圍,建議1.2-1.5倍)
public static readonly OVERFLOW_WIDTH_RATIO: number = 1.2; // 寬度放大比例
public static readonly OVERFLOW_HEIGHT_RATIO: number = 1.3; // 高度放大比例
// 動效時長(嚴格遵循系統約束,最大3500ms)
public static readonly OVERFLOW_DURATION: number = 3500;
// 動效請求標識(用於EntryFormAbility識別消息類型)
public static readonly REQUEST_OVERFLOW_MSG: string = "requestOverflow";
}

  1. 卡片基礎配置(form_config.json)

配置卡片基礎信息(尺寸、名稱、路徑等),核心添加sceneAnimationParams節點,關聯激活態對應的擴展能力:

{
"forms": [

{
  "name": "WidgetCard",
  "displayName": "場景動效互動卡片",
  "description": "支持破框動效的互動卡片示例,點擊觸發動態效果",
  "src": "./ets/widget/pages/WidgetCard.ets",
  "uiSyntax": "arkts",
  "window": {
    "designWidth": 720,
    "autoDesignWidth": true
  },
  "colorMode": "auto",
  "isDefault": true,
  "updateEnabled": true,
  "defaultDimension": "2*2", // 卡片默認尺寸(2x2格)
  "supportDimensions": ["2*2"],
  "formConfigAbility": "ability://com.example.liveformdemo.EntryAbility",
  "isDynamic": true,
  // 場景動效核心配置:關聯激活態擴展能力
  "sceneAnimationParams": {
    "abilityName": "MyLiveFormExtensionAbility"
  }
}

]
}

  1. 應用擴展能力配置(module.json5)

在extensionAbilities節點中聲明LiveForm類型擴展能力,指定激活態核心邏輯的路徑:

{
"module": {

"name": "entry",
"type": "entry",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"package": "com.example.liveformdemo",
"abilities": [
  {
    "name": "EntryAbility",
    "srcEntry": "./ets/entryability/EntryAbility.ets",
    "description": "應用主能力",
    "icon": "$media:icon",
    "label": "場景動效卡片Demo",
    "startWindowIcon": "$media:icon",
    "startWindowLabel": "場景動效卡片Demo",
    "exported": true,
    "skills": [
      {
        "entities": ["entity.system.home"],
        "actions": ["action.system.home"]
      }
    ]
  }
],
// 聲明場景動效擴展能力
"extensionAbilities": [
  {
    "name": "MyLiveFormExtensionAbility",
    "srcEntry": "./ets/myliveformextensionability/MyLiveFormExtensionAbility.ets",
    "description": "場景動效卡片激活態核心能力,負責動效渲染",
    "type": "liveForm", // 關鍵類型:必須為liveForm
    "exported": true
  }
]

}
}

  1. 頁面註冊(main_pages.json)

註冊激活態UI頁面,確保系統可正常加載動效頁面:

{
"src": [

"pages/Index", // 應用主頁面
"myliveformextensionability/pages/MyLiveFormPage" // 激活態動效頁面

]
}

(三)非激活態開發:基礎UI與動效觸發

非激活態與普通卡片行為一致,核心功能是展示基礎UI並通過點擊事件向EntryFormAbility發送動效請求消息。

// entry/src/main/ets/widget/pages/WidgetCard.ets
import { Constants } from '../../common/Constants';
import router from '@ohos.router';

@Entry
@Component
struct WidgetCard {
// 卡片初始化參數(從系統獲取卡片ID等信息)
@State formId: string = '';

build() {

Row() {
  Column() {
    Text('場景動效卡片')
      .fontSize(22)
      .fontWeight(FontWeight.Bold)
      .fontColor($r('sys.color.font_primary'))
      .margin({ bottom: 12 })
    
    Text('點擊觸發破框動效')
      .fontSize(16)
      .fontColor($r('sys.color.font_secondary'))
    
    // 可選:添加卡片圖標增強視覺效果
    Image($r('app.media.icon'))
      .width(48)
      .height(48)
      .margin({ top: 16 })
  }
  .width('100%')
  .height('100%')
  .justifyContent(FlexAlign.Center)
  .backgroundColor($r('sys.color.background_element'))
  .onClick(() => {
    // 點擊後向EntryFormAbility發送動效請求
    postCardAction(this, {
      action: 'message',
      abilityName: 'EntryFormAbility', // 接收消息的能力名稱
      params: {
        message: Constants.REQUEST_OVERFLOW_MSG, // 動效請求標識
        formId: this.formId // 傳遞當前卡片ID
      }
    });
  })
  // 初始化時獲取卡片ID
  .onPageShow(() => {
    const formInfo = AppStorage.Get('formInfo') as FormInfo;
    if (formInfo) {
      this.formId = formInfo.formId;
    }
  })
}

}
}

(四)EntryFormAbility開發:接收動效請求併發起動效

EntryFormAbility是卡片的事件處理中心,負責接收非激活態發送的動效請求,通過系統接口formProvider.requestOverflow發起“破框”動效。

// entry/src/main/ets/entryformability/EntryFormAbility.ets
import formInfo from '@ohos.app.form.formInfo';
import formProvider from '@ohos.app.form.formProvider';
import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
import { Constants } from '../common/Constants';

export default class EntryFormAbility extends FormExtensionAbility {
// 接收卡片發送的消息(動效請求)
onFormEvent(formId: string, message: string, params: Record<string, string>): void {

super.onFormEvent(formId, message, params);
// 識別動效請求消息
if (message === Constants.REQUEST_OVERFLOW_MSG) {
  this.requestOverflowEffect(formId);
}

}

// 發起破框動效請求
private async requestOverflowEffect(formId: string) {

try {
  // 1. 獲取當前卡片的實際位置和尺寸(用於計算動效區域)
  const formRect = await formProvider.getFormRect(formId);
  if (!formRect) {
    console.error('獲取卡片尺寸失敗,無法發起動效');
    return;
  }

  // 2. 根據常量比例計算動效區域(破框範圍)
  const overflowLeft = formRect.left - formRect.width * Constants.OVERFLOW_LEFT_RATIO;
  const overflowTop = formRect.top - formRect.height * Constants.OVERFLOW_TOP_RATIO;
  const overflowWidth = formRect.width * Constants.OVERFLOW_WIDTH_RATIO;
  const overflowHeight = formRect.height * Constants.OVERFLOW_HEIGHT_RATIO;

  // 3. 構造動效參數
  const overflowInfo: formInfo.OverflowInfo = {
    x: overflowLeft, // 動效區域左上角x座標
    y: overflowTop,  // 動效區域左上角y座標
    width: overflowWidth, // 動效區域寬度
    height: overflowHeight, // 動效區域高度
    duration: Constants.OVERFLOW_DURATION, // 動效時長
    needDefaultTransition: true // 是否啓用系統默認切換動效
  };

  // 4. 調用系統接口發起動效
  await formProvider.requestOverflow(formId, overflowInfo);
  console.info(`動效請求發起成功,卡片ID:${formId}`);
} catch (error) {
  console.error(`動效請求失敗:${JSON.stringify(error)}`);
}

}

// 卡片創建回調(可選:初始化卡片數據)
onAddForm(formId: string): formInfo.FormState {

return formInfo.FormState.READY;

}

// 卡片刪除回調(可選:清理資源)
onRemoveForm(formId: string): void {}
}

(五)激活態開發:動效實現與取消邏輯

激活態核心由MyLiveFormExtensionAbility(擴展能力)和MyLiveFormPage(UI頁面)組成,負責動效渲染和手動取消邏輯。

  1. 激活態擴展能力(MyLiveFormExtensionAbility.ets)

繼承LiveFormExtensionAbility,在頁面創建時初始化數據並加載動效頁面:

// entry/src/main/ets/myliveformextensionability/MyLiveFormExtensionAbility.ets
import LiveFormExtensionAbility from '@ohos.app.form.LiveFormExtensionAbility';
import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
import formInfo from '@ohos.app.form.formInfo';

export default class MyLiveFormExtensionAbility extends LiveFormExtensionAbility {
// 激活態界面對象創建回調
onLiveFormCreate(liveFormInfo: formInfo.LiveFormInfo, session: UIExtensionContentSession): void {

super.onLiveFormCreate(liveFormInfo, session);
console.info(`激活態頁面創建,卡片ID:${liveFormInfo.formId}`);

// 初始化存儲:將卡片ID、動效時長等信息存入LocalStorage,供頁面使用
const localStorage = new LocalStorage();
localStorage.set('formId', liveFormInfo.formId);
localStorage.set('duration', liveFormInfo.overflowInfo?.duration || 3500);

// 加載激活態UI頁面
session.loadContent('myliveformextensionability/pages/MyLiveFormPage', localStorage);

}

// 激活態界面對象銷燬回調(清理資源)
onLiveFormDestroy(liveFormInfo: formInfo.LiveFormInfo): void {

super.onLiveFormDestroy(liveFormInfo);
console.info(`激活態頁面銷燬,卡片ID:${liveFormInfo.formId}`);

}
}

  1. 激活態UI與動效實現(MyLiveFormPage.ets)

使用animateTo實現縮放+平移的“破框”動效,添加“取消動效”按鈕調用formProvider.cancelOverflow接口返回非激活態:

// entry/src/main/ets/myliveformextensionability/pages/MyLiveFormPage.ets
import formProvider from '@ohos.app.form.formProvider';
import { Constants } from '../../../common/Constants';

@Entry
@Component
struct MyLiveFormPage {
// 從LocalStorage獲取卡片ID和動效時長
@LocalStorageProp('formId') formId: string = '';
@LocalStorageProp('duration') duration: number = Constants.OVERFLOW_DURATION;
// 動效狀態控制
@State isAnimating: boolean = true;

build() {

Column() {
  // 動效內容:示例為旋轉+縮放的圖標
  Image($r('app.media.icon'))
    .width(64)
    .height(64)
    .animateTo({
      duration: this.duration,
      curve: Curve.EaseInOut,
      iterations: 1,
      onFinish: () => {
        // 動效結束後自動返回非激活態
        this.cancelOverflow();
      }
    }, () => {
      this.isAnimating = false;
      return {
        rotate: 360, // 旋轉360度
        scale: { x: 1.5, y: 1.5 } // 放大1.5倍(破框視覺效果)
      };
    })
  
  // 取消動效按鈕
  Button('取消動效')
    .fontSize(16)
    .width(120)
    .height(40)
    .margin({ top: 24 })
    .onClick(() => {
      this.cancelOverflow();
    })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor($r('sys.color.background_element_transparent')) // 透明背景,避免遮擋桌面

}

// 取消破框動效,返回非激活態
private async cancelOverflow() {

try {
  await formProvider.cancelOverflow(this.formId);
  console.info(`動效取消成功,卡片ID:${this.formId}`);
} catch (error) {
  console.error(`動效取消失敗:${JSON.stringify(error)}`);
}

}
}

四、調試與測試(DevEco Studio 6.0專屬操作)

  1. 卡片預覽:在DevEco Studio 6.0中打開WidgetCard.ets,點擊右上角“Preview”即可預覽非激活態UI效果;
  2. 真機調試:

  • 將測試設備與電腦連接,在IDE中選擇設備型號(需開啓設備開發者模式);
  • 點擊“Run”按鈕安裝應用,進入設備桌面添加卡片(長按桌面空白處 → 選擇“卡片” → 找到“場景動效互動卡片”添加);
  • 點擊卡片觸發動效,驗證“破框”效果和“取消動效”功能是否正常。
  1. 日誌調試:在DevEco Studio 6.0的“Logcat”面板中,篩選“formProvider”或自定義日誌標籤,查看動效請求、取消的執行狀態。

    中標題

    五、關鍵約束與注意事項

  • 動效區域約束:計算動效區域(x、y、width、height)時,需確保不超出設備屏幕範圍,否則系統會拒絕動效請求;
  • 時長約束:破框動效時長最大為3500ms,超出會被系統截斷,建議設置2000-3500ms以保證體驗;
  • 機型適配:僅支持指定華為機型,開發前需確認測試設備是否在支持列表中;
  • 功耗控制:避免頻繁觸發動效,建議添加防抖邏輯(如3秒內僅允許觸發一次);
  • DevEco Studio 6.0兼容問題:若出現“LiveFormExtensionAbility找不到”錯誤,需檢查SDK是否為API 10+(IDE默認API 12可直接使用),且擴展能力類型是否正確設置為“liveForm”;若手動調整為API 10/11版本,需確保已下載對應SDK及工具鏈。

六、總結

本文基於DevEco Studio 6.0開發環境,完整實現了場景動效互動卡片的開發流程,核心圍繞“非激活態觸發-EntryFormAbility處理-激活態動效渲染”的鏈路展開,重點講解了系統接口調用、配置文件關聯、動效區域計算等關鍵要點。通過本案例,開發者可快速掌握場景動效卡片的開發技巧,後續可根據業務需求擴展動效類型(如天氣變化動效、節日主題動效等),進一步提升應用的用户交互體驗。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.