# 第32篇:服务卡片——WidgetCard 2×2 与 2×4 实现

## 一、引言

服务卡片是鸿蒙系统的特色功能,允许用户在主屏幕直接查看应用信息。DriverLicenseExam 项目实现了 2×2 和 2×4 两种尺寸的服务卡片,展示练习进度信息。本文将深入解析服务卡片的实现。

## 二、卡片配置

### 2.1 module.json5 配置

```json
{
  "name": "EntryFormAbility",
  "srcEntry": "./ets/entryformability/EntryFormAbility.ets",
  "type": {
    "form": {
      "formVisibleNotify": true,
      "forms": [
        {
          "name": "widget_2x2",
          "src": "./ets/widget/pages/WidgetCard2X2.ets",
          "window": { "designWidth": 240, "autoDesignWidth": true },
          "colorMode": "auto",
          "isDefault": true,
          "updateEnabled": true,
          "defaultDimension": "2*2",
          "supportDimensions": ["2*2", "2*4"]
        }
      ]
    }
  }
}
```

## 三、卡片生命周期管理

### 3.1 EntryFormAbility

```ets
// EntryFormAbility.ets
export default class EntryFormAbility extends FormExtensionAbility {
  onAddForm(want: Want) {
    const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as string;
    const preferencesUtil = PreferencesUtil.getInstance();
    const preference = preferencesUtil.getPreferences(this.context);
    preferencesUtil.addFormId(preference, formId);

    const index = preferencesUtil.getPreferencesValue(preference, 'tabIndex') || 0;
    const didCount = preferencesUtil.getPreferencesValue(preference, 'didCount') || 0;
    const totalCount = preferencesUtil.getPreferencesValue(preference, 'totalCount') || 0;

    const data = {
      index: index,
      didCount: didCount,
      totalCount: totalCount,
    };
    return formBindingData.createFormBindingData(data);
  }

  onRemoveForm(formId: string) {
    const preferencesUtil = PreferencesUtil.getInstance();
    preferencesUtil.removeFormId(this.context, formId);
  }
}
```

## 四、卡片 UI 布局

### 4.1 2×2 卡片

```ets
// WidgetCard2X2.ets
@Entry
@Component
struct WidgetCard2X2 {
  @StorageProp('didCount') didCount: number = 0;
  @StorageProp('totalCount') totalCount: number = 0;

  build() {
    Column() {
      Text('练习进度').fontSize(14).fontColor('#FFFFFF');
      Text(`${this.didCount}/${this.totalCount}`)
        .fontSize(24)
        .fontColor('#64BB5C');
      Progress({ value: this.didCount, total: this.totalCount })
        .width('100%')
        .color('#64BB5C');
    }
    .padding(12)
    .width('100%')
    .height('100%')
    .backgroundColor('#1A1A2E');
  }
}
```

## 五、卡片数据更新

```ets
// MainEntry.ets 中更新卡片数据
updateForm(index: number) {
  const preferencesUtil = PreferencesUtil.getInstance();
  const preference = preferencesUtil.getPreferences(this.getUIContext().getHostContext() as Context);
  const formIds = preferencesUtil.getFormIds(preference);

  preferencesUtil.preferencesPut(preference, 'tabIndex', index);
  preferencesUtil.preferencesPut(preference, 'didCount', this.didCount);
  preferencesUtil.preferencesPut(preference, 'totalCount', this.totalCount);

  const formInfo = formBindingData.createFormBindingData(newData);
  formIds.forEach((id: string) => {
    formProvider.updateForm(id, formInfo)
      .then(() => Logger.info('MainEntry', '更新成功'))
      .catch((err) => Logger.error('MainEntry', '更新失败: ' + JSON.stringify(err)));
  });
}
```

## 六、总结

服务卡片通过 FormExtensionAbility 管理卡片生命周期,结合 Preferences 持久化卡片数据,实现了练习进度的实时展示。

---

**关键源码文件:**
- `products/entry/src/main/ets/entryformability/EntryFormAbility.ets`
- `products/entry/src/main/ets/widget/pages/WidgetCard2X2.ets`
- `products/entry/src/main/ets/widget/pages/WidgetCard2X4.ets`
- `products/entry/src/main/ets/pages/MainEntry.ets`

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐