大家好,我是陈杨,一名有着8 年前端开发经验、6 年技术写作积淀的鸿蒙开发者,也是鸿蒙生态里的一名极客。

曾因前端行业的危机感居安思危,果断放弃饱和的 iOS、安卓赛道,在鸿蒙 API9 发布时,凭着前端技术底子,三天吃透 ArkTS 框架,快速上手鸿蒙开发。三年深耕,我不仅打造了鸿蒙开源图表组件库「莓创图表」,闯进过创新赛、极客挑战赛总决赛,更带着团队实实在在做出了成果 —— 目前已成功上架11 款鸿蒙应用,涵盖工具、效率、创意等多个品类,包括JLPT、REFLEX PRO、国潮纸刻、Wss 直连、ZenithDocs Pro、圣诞相册、CSS 特效等,靠这些自研产品赚到了转型后的第一桶金。

从前端转型到鸿蒙掘金,靠的不是运气,而是选对赛道的眼光和快速落地的执行力。今天这篇文章主要带大家了解卡片最新的能力,我们从应用内拉起卡片管理加桌锁屏卡片开发背板透明卡片开发三个核心场景出发,带大家一步步掌握不同类型卡片的实现逻辑与代码细节,同时解析开发中的关键约束与注意事项。这三个功能也是在指令魔方APP中使用最多的场景了

在这里插入图片描述

一、应用内拉起卡片管理加桌:让用户主动添加卡片

应用内加桌功能的核心是通过formProvider模块的openFormManager接口,在应用内提供 “添加卡片到桌面” 的入口,用户点击后可直接拉起系统统一的卡片管理页面,完成卡片添加操作。这种方式相比传统的 “长按应用图标加桌”,能更精准地引导用户留存卡片,提升功能触达率。

1.1 核心开发步骤

步骤 1:导入必要依赖

首先需要导入FormKit(卡片核心能力)、BasicServicesKit(错误处理)、AbilityKit(Want 对象,用于传递卡片信息)相关模块,为后续接口调用做准备。

步骤 2:设计加桌入口 UI

在应用页面中添加一个按钮作为触发入口,按钮点击事件中构造Want对象(包含卡片所属应用包名、能力名、尺寸等关键参数),并调用openFormManager接口拉起卡片管理页面。

步骤 3:处理异常场景

通过try-catch捕获接口调用可能出现的错误(如参数错误、系统权限不足等),并通过日志打印或 Toast 提示用户,提升开发调试效率与用户体验。

1.2 完整代码实现

// entry/src/main/ets/pages/Index.ets
import { formProvider } from '@kit.FormKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { Want } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI'; // 用于Toast提示

@Entry
@Component
struct CardAddToDesktopPage {
  build() {
    Row({ space: 0 }) {
      Column({ space: 10 }) {
        // 应用内加桌按钮,文案通过资源文件引用,支持多语言
        Button($r('app.string.add_card_to_desktop'))
          .width('80%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            // 1. 构造Want对象:传递卡片关键信息
            const cardWant: Want = {
              bundleName: 'com.example.arktscarddemo', // 你的应用包名
              abilityName: 'EntryFormAbility', // 卡片对应的Ability名(需与form_config.一致)
              parameters: {
                'ohos.extra.param.key.form_dimension': 2, // 卡片尺寸(2对应2*2,1对应1*1)
                'ohos.extra.param.key.form_name': 'main_widget', // 卡片名(需与form_config.一致)
                'ohos.extra.param.key.module_name': 'entry' // 模块名(默认entry)
              }
            };

            try {
              // 2. 调用openFormManager拉起卡片管理页面
              formProvider.openFormManager(cardWant);
            } catch (error) {
              // 3. 异常处理:打印日志+Toast提示
              const err = error as BusinessError;
              console.error(`卡片加桌失败:code=${err.code}, message=${err.message}`);
              promptAction.openToast({
                message: `添加失败:${err.message}`,
                duration: 2000
              });
            }
          })

        Text('点击按钮后,选择"添加至桌面"即可将卡片添加到桌面')
          .fontSize(14)
          .fontColor('#666666')
          .textAlign(TextAlign.Center)
          .width('80%')
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)
    }
    .height('100%')
    .backgroundColor('#f5f5f5')
  }
}

1.3 资源文件配置(多语言支持)

为按钮文案配置资源文件,避免硬编码,方便后续多语言扩展:

// entry/src/main/resources/base/element/string.
{
  "string": [
    {
      "name": "add_card_to_desktop",
      "value": "添加应用卡片到桌面"
    }
  ]
}

1.4 效果与注意事项

  • 用户操作流程:点击应用内按钮 → 拉起系统卡片管理页面 → 预览卡片 → 点击 “添加至桌面” → 卡片成功显示在桌面。
  • 关键约束
    • Want对象中的bundleNameabilityNameform_name必须与form_config.中配置的一致,否则会导致卡片无法识别。
    • 卡片尺寸(form_dimension)需在form_config.supportDimensions中定义,支持 1_1、2_2 等常见尺寸。

二、锁屏卡片开发:不解锁也能获取关键信息

从 API Version 18 开始,HarmonyOS 支持在锁屏界面显示卡片,用户无需解锁设备即可查看天气、时钟、运动数据等浅层信息,同时支持快捷操作(如一键打卡、播放控制)。锁屏卡片的核心是 “信息浅层触达”,但需严格遵守隐私与尺寸约束。

2.1 锁屏卡片核心特征与约束

类别 具体要求
设备支持 仅手机、平板设备
尺寸限制 仅支持 1_1(占 1 个添加位)、1_2(占 2 个添加位)
隐私安全 禁止展示用户隐私数据(如短信、通讯录、支付信息)
开放能力 需申请 “锁屏卡片” 开放能力,通过华为 AGC 审核后才能使用

2.2 开发步骤:配置 + 能力申请 + 代码实现

步骤 1:配置 form_config.(关键)

锁屏卡片必须在配置文件中声明renderingMode(渲染模式)和supportDimensions(支持尺寸),否则无法在锁屏界面显示:

// entry/src/main/resources/base/profile/form_config.
{
  "forms": [
    {
      "name": "lockscreen_widget", // 卡片名
      "displayName": "$string:lockscreen_widget_name", // 卡片显示名(资源引用)
      "description": "$string:lockscreen_widget_desc", // 卡片描述
      "src": "./ets/widget/pages/LockscreenCard.ets", // 卡片UI文件路径
      "uiSyntax": "arkts", // 开发语言
      "isDynamic": true, // 是否动态卡片(支持数据更新)
      "isDefault": true, // 是否默认卡片
      "updateEnabled": true, // 是否允许更新
      "scheduledUpdateTime": "08:00", // 定时更新时间(如每天8点更新天气)
      "renderingMode": "autoColor", // 渲染模式:autoColor(自适应系统主题)/singleColor(单色)
      "defaultDimension": "1*2", // 默认尺寸(必须是supportDimensions中的值)
      "supportDimensions": ["1*1", "1*2"] // 支持尺寸(锁屏卡片仅支持这两个)
    }
  ]
}
步骤 2:申请锁屏卡片开放能力

由于锁屏卡片涉及用户隐私与系统界面,需通过华为 AGC 申请开放能力,步骤如下:

  1. 登录AppGallery Connect,进入你的项目 → 选择应用。
  2. 进入 “开放能力管理” 页面,找到 “锁屏卡片”,点击 “申请”。
  3. 填写申请信息:
    • 申请原因:说明卡片用途(如 “展示用户当日运动步数,不包含隐私数据”),不超过 256 字符。
    • 上传附件(选填):可上传卡片 UI 设计图,证明符合隐私规范。
  4. 提交后等待 1-3 个工作日审核,审核通过后勾选能力开关并保存。
步骤 3:实现卡片 UI 与数据更新

以 “运动步数锁屏卡片” 为例,实现简单 UI 与数据展示(动态卡片需结合formBindingData更新数据):

// entry/src/main/ets/widget/pages/LockscreenCard.ets
import { postCardAction } from '@kit.FormKit';

@Entry
@Component
struct LockscreenStepCard {
  // 模拟运动步数数据(实际应从应用或后端获取)
  private stepCount: number = 8567;

  build() {
    Column({ space: 8 }) {
      Text('今日运动')
        .fontSize(14)
        .fontColor('#ffffff')
        .opacity(0.8)

      Row({ space: 4 }) {
        Text(this.stepCount.toString())
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ffffff')

        Text('步')
          .fontSize(14)
          .fontColor('#ffffff')
          .opacity(0.8)
      }

      // 快捷按钮:点击跳转到应用运动详情页
      Button('查看详情')
        .width('60%')
        .height(32)
        .fontSize(12)
        .backgroundColor('#ffffff')
        .fontColor('#007aff')
        .onClick(() => {
          postCardAction(this, {
            action: 'router', // 跳转类型
            abilityName: 'EntryAbility', // 目标Ability
            params: {
              page: 'pages/SportDetail' // 目标页面
            }
          });
        })
    }
    .width('100%')
    .height('100%')
    .padding(12)
    .backgroundColor('#007aff') // 锁屏卡片背景建议与系统主题协调
  }
}

2.3 用户操作流程

  1. 进入锁屏编辑态:在锁屏界面双手捏合,出现 4 个卡片添加位。
  2. 添加卡片:点击添加位 → 弹出锁屏卡片管理页面 → 选择你的卡片 → 卡片添加成功。
  3. 删除卡片:在锁屏编辑态,点击卡片右上角 “-” 即可删除。

三、背板透明卡片开发:更灵活的 UI 设计

从 API Version 22 开始,HarmonyOS 支持卡片背板透明,开发者可实现 “仅显示内容、无背景” 的轻量化卡片,满足个性化 UI 设计需求(如日程卡片、待办卡片)。但需注意:透明区域不能过大,且必须通过开放能力申请。

3.1 核心约束与开发准备

  • 透明区域限制:非透明区域需≥10%,避免用户误以为无卡片,导致误操作。
  • 字体显示:建议使用系统推荐的反色字体(根据桌面壁纸自动适配颜色),确保文字清晰可见。
  • 开放能力:需申请 “背板透明卡片” 能力,且必须上传 UI 设计释义材料(证明透明设计的合理性)。

3.2 开发步骤:配置 + 能力申请 + 反色字体适配

步骤 1:配置 form_config.(开启透明)

在配置文件中添加transparencyEnabled: true,声明卡片为透明背板:

// entry/src/main/resources/base/profile/form_config.
{
  "forms": [
    {
      "name": "transparent_widget",
      "displayName": "$string:transparent_widget_name",
      "description": "$string:transparent_widget_desc",
      "src": "./ets/widget/pages/TransparentCard.ets",
      "uiSyntax": "arkts",
      "isDynamic": true,
      "isDefault": true,
      "updateEnabled": true,
      "defaultDimension": "2*2",
      "supportDimensions": ["2*2"],
      "transparencyEnabled": true, // 开启背板透明
      "window": {
        "designWidth": 720, // 设计宽度,适配不同屏幕
        "autoDesignWidth": true
      }
    }
  ]
}
步骤 2:申请透明卡片开放能力

与锁屏卡片申请流程类似,需在 AGC 中申请 “背板透明卡片” 能力,关键差异在于:

  • 申请原因:需详细说明透明场景(如 “待办卡片仅显示文字内容,透明背景避免遮挡桌面壁纸”)。
  • 上传附件必填,需提供卡片 UI 设计图(标注透明区域与非透明区域),证明符合 “非透明区域≥10%” 的约束。
步骤 3:实现透明卡片与反色字体

透明卡片的核心是将backgroundColor设为Color.Transparent,并通过系统提供的HOST_BG_INVERSE_COLOR_KEY获取反色字体,适配不同桌面壁纸:

3.3.1 卡片 UI 实现(TransparentCard.ets)
// entry/src/main/ets/widget/pages/TransparentCard.ets
import { postCardAction } from '@kit.FormKit';
import { LocalStorageProp, Watch } from '@ohos.arkui.ui';

@Entry
@Component
struct TransparentTodoCard {
  // 从LocalStorage获取系统推荐的反色字体颜色(在EntryFormAbility中设置)
  @LocalStorageProp('textColor') @Watch('onTextColorChange') textColor: string = '#333333';

  // 待办数据(实际应从应用获取)
  private todos: string[] = ['完成HarmonyOS卡片开发', '提交AGC能力申请', '测试透明卡片适配'];

  build() {
    Column({ space: 12 }) {
      Text('今日待办')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.textColor)

      List({ space: 8 }) {
        ForEach(this.todos, (todo) => {
          ListItem() {
            Text(todo)
              .fontSize(14)
              .fontColor(this.textColor)
              .width('100%')
              .padding(8)
              .backgroundColor('#ffffff')
              .opacity(0.7) // 非透明区域,满足≥10%约束
              .borderRadius(4)
          }
        })
      }
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .padding(16)
    .backgroundColor(Color.Transparent) // 背板透明
    .onClick(() => {
      // 点击卡片跳转到待办详情页
      postCardAction(this, {
        action: 'router',
        abilityName: 'EntryAbility',
        params: { page: 'pages/TodoDetail' }
      });
    })
  }

  // 监听字体颜色变化,打印日志(调试用)
  private onTextColorChange() {
    console.info(`透明卡片字体颜色更新:${this.textColor}`);
  }
}
3.3.2 反色字体颜色设置(EntryFormAbility.ets)

在卡片 Ability 的生命周期中,通过want参数获取系统推荐的反色颜色,并同步到卡片 UI:

// entry/src/main/ets/entryformability/EntryFormAbility.ets
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';

// 定义反色颜色数据结构(与系统返回格式一致)
interface TextColorInfo {
  mTextColor: string; // 字体颜色值(如#ffffff)
  mWallpaperType: number; // 壁纸类型(无需处理,仅传递)
}

export default class EntryFormAbility extends FormExtensionAbility {
  // 卡片添加时触发:设置初始反色字体
  onAddForm(want: Want) {
    console.info('透明卡片:onAddForm触发');
    let formData: Record<string, string> = {};
    if (want?.parameters) {
      // 从want中获取系统推荐的反色颜色
      const colorInfo = want.parameters[formInfo.FormParam.HOST_BG_INVERSE_COLOR_KEY] as TextColorInfo;
      if (colorInfo) {
        formData['textColor'] = colorInfo.mTextColor;
        console.info(`获取到反色字体:${colorInfo.mTextColor}`);
      } else {
        formData['textColor'] = '#333333'; // 默认颜色(兜底)
        console.warn('未获取到反色字体,使用默认颜色');
      }
    }
    // 将颜色数据传递给卡片UI
    return formBindingData.createFormBindingData(formData);
  }

  // 卡片更新时触发:同步最新反色字体
  onUpdateForm(formId: string, wantParams?: Record<string, Object>) {
    console.info('透明卡片:onUpdateForm触发');
    let textColor = '#333333';
    if (wantParams) {
      const colorInfo = wantParams[formInfo.FormParam.HOST_BG_INVERSE_COLOR_KEY] as TextColorInfo;
      if (colorInfo) {
        textColor = colorInfo.mTextColor;
      }
    }
    // 更新卡片数据
    const formData = formBindingData.createFormBindingData({ textColor });
    formProvider.updateForm(formId, formData)
      .then(() => console.info('透明卡片字体更新成功'))
      .catch((err) => console.error(`透明卡片更新失败:${.stringify(err)}`));
  }

  // 其他生命周期方法(按需实现)
  onCastToNormalForm(formId: string) {}
  onFormEvent(formId: string, message: string) {}
  onRemoveForm(formId: string) {}
  onAcquireFormState(want: Want) {
    return formInfo.FormState.READY;
  }
}

3.3 效果预览

透明卡片添加到桌面后,仅显示 “今日待办” 标题与待办列表,背景完全透明,可清晰看到桌面壁纸;当用户更换壁纸时,字体颜色会自动切换为系统推荐的反色(如壁纸为深色时,字体变为白色),确保可读性。

四、三类卡片开发对比与总结

卡片类型 核心场景 关键 API / 配置 开放能力申请 尺寸约束
应用内加桌卡片 应用内引导用户添加卡片 formProvider.openFormManager
、Want 对象
无需 支持 1_1、2_2 等(需在 form_config. 定义)
锁屏卡片 不解锁查看浅层信息 renderingMode: autoColor/singleColor 需申请 “锁屏卡片” 仅支持 1_1、1_2
背板透明卡片 轻量化 UI 设计,避免遮挡壁纸 transparencyEnabled: true
HOST_BG_INVERSE_COLOR_KEY
需申请 “背板透明卡片”(必填 UI 材料) 无特殊尺寸,但非透明区域≥10%

开发建议

  1. 优先适配主流尺寸:无论是哪种卡片,优先支持 1_1、2_2 尺寸,覆盖绝大多数设备的桌面布局。
  2. 严格遵守隐私规范:锁屏卡片禁止展示隐私数据,透明卡片需确保非透明区域足够,避免用户误操作。
  3. 重视异常处理:卡片加桌、更新过程中可能出现参数错误、系统权限不足等问题,需通过try-catch与日志打印快速定位问题。
  4. 测试多场景适配:透明卡片需测试不同壁纸下的字体可读性,锁屏卡片需测试锁屏编辑态的添加 / 删除流程,确保用户体验一致。

五、总结

通过本文的实战教程,相信大家已掌握 HarmonyOS 三类核心 ArkTS 卡片的开发方法。后续可结合具体业务场景,进一步优化卡片的交互逻辑与数据更新策略,让卡片成为提升应用用户留存与使用效率的关键载体。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐