WWDC Quick Look 💓 By SwiftGGTeam
Design dynamic Live Activities

Design dynamic Live Activities

观看原视频

Highlight

Live Activities 让应用可以在锁屏、StandBy 和灵动岛三个系统位置展示实时信息。Apple 为每个场景提供了独特的设计规范,核心目标是让用户在离开应用后仍能跟踪正在进行的任务。

核心内容

锁屏:图形化布局,一眼获取关键信息

以前用户想查看外卖进度或比赛比分,需要解锁手机、找到应用、打开查看。锁屏通知只能显示静态信息,更新时整段替换,体验生硬。

Live Activities 改变了这个流程。它在锁屏通知列表顶部常驻,用丰富的图形化布局展示实时数据,内容可以无缝更新。

01:18)锁屏上的 Live Activity 使用 14pt 边距,与通知对齐。但设计时不要复制通知布局,要创建专属于所展示信息的独特布局。

01:55)思考用户最需要什么信息,优先放大这些元素。Timer 的 Live Activity 除了显示名称和剩余时间,还提供了暂停和取消按钮。但按钮只应用于控制活动本身的核心操作,因为它们会占用展示信息的空间。

品牌个性:从应用图标延续视觉识别

02:27)Live Activity 应该和应用共享相同的视觉个性。从应用图标提取颜色和字体属性是最直接的方式。TV 应用的 Live Activity 使用了和应用图标相同的背景色和前景色。

不要在明暗模式之间改变颜色,这会破坏视觉关联。大胆用色可以让 Live Activity 脱颖而出,也可以根据内容动态变化颜色。

如果使用品牌标志,要把它融入布局本身,不要直接使用整个应用图标。

空间效率:动态调整高度

03:44)锁屏可能同时显示音乐播放器、通知和 Live Activities,所以布局要尽量紧凑。调整元素大小和位置,让它们更好地组合在一起。

04:05)更高级的做法是动态改变高度。打车应用在等待司机时信息少,布局保持紧凑;司机接单后展开显示更多信息。比赛进入中场休息时,逐节比分区域可以收起。

过渡动画:让更新更生动

04:38)状态变化时除了调整高度,还可以给单个元素应用过渡动画:

  • 数字变化用 numericContentTransition
  • 图形和文本替换用 contentReplace transition
  • 也可以自定义组合 scale、opacity、position 动画

05:06)Nearby Friends 示例中,地图上的标记会平滑过渡到新位置。列表中的项目移动时,只动画正在移动的那一行,其他行淡入淡出,避免重叠。

提醒与结束

05:33)重要更新需要提醒用户时,使用 alert 功能。这会点亮屏幕并播放通知音。布局中要突出触发提醒的信息。

05:49)活动结束后要及时移除,不要让它在锁屏上停留太久,否则用户每次都要手动关闭。

StandBy:环境信息显示器

06:04)StandBy 是 iOS 17 新功能,iPhone 横放时变成环境信息显示器。Live Activity 在这里放大 200%,背景色自动扩展到全屏。

06:35)如果布局有贴边元素,放大后会被传感器区域裁切。建议用分隔线或容器形状分隔不同区域。也可以完全移除背景色,让布局融入设备边框,获得更大的显示面积。

07:22)StandBy 有夜间模式,低光环境下显示会变成红色调。Live Activity 自动适配,但要检查颜色对比度是否足够。

灵动岛:三种形态的设计

07:42)灵动岛是软硬件融合的系统层,可以有机地在不同形态之间变形。它的设计灵感来自生物形态和运动,有弹性、有生命力。

Compact 视图

11:09)最常见的形态。目标是让用户在使用手机时也能关注后台活动。内容要紧贴传感器区域,不要浪费空间。尽量填满整个视图,避免左侧留白。如果需要展示多个会话,可以交替显示。

12:18)需要提醒用户时,优先扩展灵动岛而不是发送推送通知。

Expanded 视图

12:41)用户长按灵动岛进入。展示更多信息,提供核心控制。要抓住活动的本质,不要太多也不要太少。保持 compact 和 expanded 之间元素的相对位置一致。

13:39)布局时避免顶部留出”额头”强调传感器区域。应该紧贴传感器,让内容环绕它,让传感器几乎消失。

Minimal 视图

13:53)多个会话同时存在时显示。不要只用 logo,要想办法在这个极小的空间里继续传达信息。

同心圆布局原则

09:52)灵动岛对内部元素的形状和位置很敏感。圆形元素应该与灵动岛形状同心,保持均匀边距。非圆形元素的视觉重心也要舒适地嵌在灵动岛内部。

一个技巧:模糊对象,检查结果形状是否与外边框尽可能同心。这样可以把内容放在光学上最舒适的位置。

10:35)放置内容时保持与灵动岛边缘的同心边距,避免戳到角落。可以把内容向内推,或者把容器圆角化。

详细内容

锁屏布局要点

01:23)Live Activity 在锁屏使用 14pt 边距,与通知对齐。虽然布局不同,但元素可以在两侧对齐,保持一致的视觉节奏。

关键设计原则:

  • 图形化布局优于文字列表
  • 优先展示最重要的信息
  • 按钮只用于核心操作
  • 动态调整高度适应信息量

颜色与品牌

03:24)Live Activity 提供的背景色和前景色会被系统用于生成关闭按钮。要确保生成的按钮看起来正确。

// ActivityAttributes 中配置颜色
struct DeliveryAttributes: ActivityAttributes {
    public struct ContentState: Codable, Hashable {
        var status: String
        var eta: Date
    }
    
    var orderId: String
    var restaurantName: String
}

// 在 ActivityConfiguration 中设置外观
ActivityConfiguration(for: DeliveryAttributes.self) { context in
    LockScreenLiveActivityView(context: context)
} dynamicIsland: { context in
    DynamicIsland {
        // Compact leading
        DynamicIslandExpandedRegion(.leading) {
            // 内容紧贴传感器
        }
        // Compact trailing
        DynamicIslandExpandedRegion(.trailing) {
            // 核心信息
        }
        // Expanded
        DynamicIslandExpandedRegion(.center) {
            // 完整布局
        }
    } compactLeading: {
        // 最小化 leading
    } compactTrailing: {
        // 最小化 trailing
    } minimal: {
        // 最小视图
    }
}

关键点

  • ActivityConfiguration 定义 Live Activity 的外观
  • dynamicIsland 闭包配置灵动岛的三种形态
  • DynamicIslandExpandedRegion 定义 expanded 视图的区域划分
  • compactLeading/compactTrailing 定义 compact 形态的左右内容
  • minimal 定义多个会话时的最小视图

过渡动画实现

04:47)系统提供默认过渡效果:

// 数字过渡
text("\(remainingTime)")
    .contentTransition(.numericText(countsDown: true))

// 内容替换过渡
text(status)
    .contentTransition(.identity)
    .transition(.push(from: .bottom))

关键点

  • .numericText(countsDown:) 让数字像计时器一样倒数
  • .identity 配合 .transition 可以自定义替换动画
  • 列表项移动时,只动画目标项,其他项淡入淡出

StandBy 适配

06:18)StandBy 下 Live Activity 放大 200%,背景色自动扩展。需要注意:

  • 贴边元素会被裁切,使用分隔线或容器
  • 移除背景可以获得更大显示面积
  • 所有素材需要足够高的分辨率
  • 检查夜间模式(红色调)下的对比度

核心启发

为外卖/配送应用添加实时追踪

  • 做什么:用户下单后,在锁屏和灵动岛实时展示配送进度
  • 为什么值得做:用户不需要反复打开应用查看,体验更流畅
  • 怎么开始:用 ActivityKit 创建 ActivityAttributes,在订单确认时调用 request(attributes:contentState:pushType:)

为运动/健身应用设计 Live Activity

  • 做什么:跑步、骑行时,在灵动岛展示实时配速、心率和距离
  • 为什么值得做:用户可以在使用其他应用时持续关注运动数据
  • 怎么开始:在 ActivityConfiguration 中配置 compact 和 expanded 视图,用 numericText 过渡动画更新数据

为赛事应用创建比分追踪

  • 做什么:比赛进行中,在锁屏和灵动岛实时更新比分和关键事件
  • 为什么值得做:用户可以在做其他事情时不错过比赛进展
  • 怎么开始:动态调整 Live Activity 高度——正常比赛时展开显示详细数据,中场休息时收起

为打车应用设计状态流转

  • 做什么:从叫车到到达,每个阶段在灵动岛展示不同的信息和操作
  • 为什么值得做:不同阶段用户关注的信息不同,动态调整布局更高效
  • 怎么开始:定义多个 ContentState,状态变化时更新 ActivitycontentState,配合 contentReplace 过渡动画

关联 Session

评论

GitHub Issues · utterances