HarmonyOS 7 新特性(三十八)|互动卡片:摇一摇、破框与状态机 封面

HarmonyOS 7 的互动卡片让桌面内容从静态信息入口变成可触发、可动效、可与应用协作的轻量界面。摇一摇、前景元素出框、静态转动态等效果很吸引人,但卡片运行环境、内存预算、生命周期和事件能力都与普通页面不同。

高质量卡片不是把应用首页缩小,而是选择一个高频任务,用有限状态和明确事件在桌面完成。本文从卡片选型、状态机、事件路由、动效预算和降级验收展开。

一、先判断该做静态还是动态

静态卡片内存更小,适合信息展示、刷新和快捷跳转;动态卡片支持更丰富交互、动效和滑动。选型依据应是任务需求,不是视觉偏好。

interface WidgetRequirement {
  needsAnimation: boolean
  needsGesture: boolean
  needsListInteraction: boolean
  updateFrequencyPerHour: number
}

function chooseWidget(r: WidgetRequirement): 'STATIC' | 'DYNAMIC' {
  return r.needsAnimation || r.needsGesture || r.needsListInteraction
    ? 'DYNAMIC' : 'STATIC'
}

只展示天气、票务状态或待办数量时,静态卡片通常更可靠。

二、卡片只承载一个核心任务

一张卡片最好回答一个问题或完成一个动作,例如“下一班车何时到”“今天还剩几个待办”“继续上次播放”。不要塞入完整导航、多个二级列表和复杂表单。

type WidgetModel = {
  title: string
  primaryValue: string
  secondaryText?: string
  primaryAction: 'OPEN' | 'REFRESH' | 'TOGGLE'
  updatedAt: number
  revision: number
}

模型字段受控,避免把整个业务对象序列化给卡片。

三、静态态与互动状态分离

卡片初始呈现应在不播放动效时也能表达信息。摇一摇等事件只是增强,不是唯一入口。

type CardState = 'STATIC' | 'ARMED' | 'ANIMATING' | 'RESULT' | 'COOLDOWN'

function transition(state: CardState, event: 'SHAKE' | 'END' | 'RESET'): CardState {
  if (state === 'STATIC' && event === 'SHAKE') return 'ANIMATING'
  if (state === 'ANIMATING' && event === 'END') return 'RESULT'
  if (event === 'RESET') return 'STATIC'
  return state
}

状态机应拒绝动画期间重复触发,避免堆积任务和状态错乱。

HarmonyOS 7 新特性(三十八)|互动卡片:摇一摇、破框与状态机 核心链路

四、动效资源提前准备

卡片不是无限内存画布。图片、序列帧和粒子资源要压缩、分辨率匹配并控制数量。启动时临时解码大量资源会出现首帧空白。

interface MotionBudget {
  maxDurationMs: number
  maxLayers: number
  maxBitmapBytes: number
  maxConcurrentAnimations: number
}

const CARD_BUDGET: MotionBudget = {
  maxDurationMs: 1200,
  maxLayers: 6,
  maxBitmapBytes: 2 * 1024 * 1024,
  maxConcurrentAnimations: 2
}

具体限制以目标设备与官方规范为准,业务内部还应设置更保守的预算。

五、破框效果不能破坏可读性

前景元素出框可以制造空间感,但关键文本、操作按钮和状态不能跟随出框。需要定义安全区、裁剪区和触控区。

type SafeArea = { left: number; top: number; right: number; bottom: number }

function insideSafeArea(x: number, y: number, area: SafeArea) {
  return x >= area.left && x <= area.right && y >= area.top && y <= area.bottom
}

在极窄、默认和极宽预览尺寸分别验证,避免只在设计稿尺寸正确。

六、事件通过稳定协议传递

动态 ArkTS 卡片可使用 postCardAction 与提供方应用协作,常见有 router、message 和 call。事件参数应版本化、白名单化。

postCardAction(this, {
  action: 'router',
  bundleName: 'com.example.app',
  abilityName: 'EntryAbility',
  params: {
    route: '/task/today',
    source: 'widget',
    protocolVersion: 2
  }
})

应用收到参数后再次校验,不能把任意字符串当成内部路由或命令执行。

七、更新使用 revision 防止倒退

卡片可能同时收到定时刷新、应用更新和云端推送。旧结果晚到时不能覆盖新状态。

function acceptUpdate(current: WidgetModel, incoming: WidgetModel): WidgetModel {
  if (incoming.revision <= current.revision) return current
  return incoming
}

时间戳不能完全替代版本号,因为设备时钟可能偏差。服务端或业务存储生成单调 revision 更稳妥。

八、离线和错误态必须独立设计

卡片刷新失败时保留最近成功内容,并标记更新时间;认证过期时展示“打开应用继续”,而不是空白。敏感信息在锁屏或账号退出时立即隐藏。

type WidgetViewState =
  | { kind: 'READY'; model: WidgetModel }
  | { kind: 'STALE'; model: WidgetModel; retryAfter: number }
  | { kind: 'AUTH_REQUIRED' }
  | { kind: 'EMPTY' }

错误提示应短而可行动,详细原因留在应用内。

九、减少动态与无障碍

用户开启减少动态时,摇一摇可直接切换结果或使用淡入,不播放位移和出框动画。卡片元素需要可理解名称、顺序和足够触控区域。

关键信息不能只靠颜色和运动表达。动画完成后读屏应获得新的状态,而不是重复朗读所有装饰元素。

十、测试不仅看预览器

官方工具支持多尺寸预览,但卡片不支持普通页面式调试,必须在真实桌面验证添加、删除、刷新、前后台、重启和系统资源回收。覆盖不同字体比例、语言、深浅色和弱网。

指标包括首次显示时间、更新成功率、内存、动画丢帧、重复事件、误触和从卡片到目标页的到达率。

十一、上线清单

  • 静态/动态选型有明确任务依据;
  • 卡片只承载一个核心任务;
  • 无动效时仍能正确表达状态;
  • 摇一摇和动画状态机防重复触发;
  • 资源、层数和时长有预算;
  • postCardAction 参数版本化并二次校验;
  • 更新使用 revision 防止旧状态覆盖;
  • 离线、过期、锁屏和减少动态均有降级;
  • 多尺寸预览与真实桌面验收完成。

HarmonyOS 7 新特性(三十八)|互动卡片:摇一摇、破框与状态机 验收清单

结语

互动卡片的创新不在于播放一次华丽动画,而在于用最小界面完成高频任务。把动态效果放在稳定静态态之上,用受控事件和单调版本连接应用,再用资源预算与无障碍降级守住边界,卡片才能既生动又可靠。

官方参考

  • 创建服务卡片:https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/ide-service-widget
  • 卡片事件能力说明:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-ui-widget-event-overview-V13
  • HarmonyOS 7 新能力一览:https://developer.huawei.com/consumer/cn/features/
Logo

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

更多推荐