Dynamic Island — iPhone 14 Pro 及所有 iPhone 15/16 顶部的交互区域,它将通知、后台活动和系统指示器统一在一个动态区域中。与传统刘海(notch)不同,Dynamic Island 会根据当前上下文改变形状和大小。根据 Apple 的数据(WWDC 2024),用户平均每天与 Dynamic Island 交互 12 次 — 通过点按、长按以及使用 ActivityKit 的 Live Activities。有关 iOS 动画的更多信息,请阅读 关于 Corner Radius 的文章。
要点
Dynamic Island — 基于 Apple 软硬件解决方案的交互区域,于 2022 年 9 月随 iPhone 14 Pro 一同推出。从物理上讲,它是一个药丸形状的切口,周围环绕着 OLED 像素,可以动态改变颜色和形状。Apple 将摄像头和 Face ID 的硬件隔间与其周围的黑色区域的软件渲染相结合,创造出「活」岛屿的错觉。
Dynamic Island 的主要目标是消除系统通知和活动内容之间的鸿沟。通知不再出现在屏幕中央(如 Android)或顶部横幅中(如旧版 iOS),而是 Dynamic Island 将它们直接集成到硬件区域中。这减少了注意力分散,创造了统一空间的感觉。
根据 Apple 的数据(iOS 17 采用统计,2024),Dynamic Island 在 38% 的活跃 iPhone 上可用。从 iPhone 15(2023)开始,所有系列型号都获得了 Dynamic Island,包括基础型号。在 iOS 18 中,Apple 扩展了 Live Activities API,直接在 Dynamic Island 上添加了倒计时计时器和体育比赛结果的支持。
Dynamic Island 可在 iPhone 14 Pro、iPhone 14 Pro Max、iPhone 15、iPhone 15 Plus、iPhone 15 Pro、iPhone 15 Pro Max、iPhone 16、iPhone 16 Plus、iPhone 16 Pro、iPhone 16 Pro Max 上使用。iPad 上没有 Dynamic Island。使用 Dynamic Island 进行开发需要 Xcode 14.1+ 和 iOS 16.1+。
Dynamic Island 支持三种显示状态:紧凑(compact)、最小(minimal)和扩展(expanded)。状态之间的转换使用 UIKit 动画和 Core Animation 进行动画处理。系统自行管理活动的优先级:如果多个应用程序同时尝试显示内容,iOS 会根据最后活动的开始时间使用队列。
| 状态 | 尺寸 | 内容 | 示例 |
|---|---|---|---|
| Compact | 49×18 pt | 应用程序图标 + 系统图标 | 计时器、音乐、通话 |
| Minimal | 最大 66×18 pt | 图标 + 简短文本 | 导航指示、步数 |
| Expanded | 最大 364×160 pt | 带内容的完整 widget | 体育比分、出租车状态 |
紧凑状态 — 当有一个后台任务活动时 Dynamic Island 的标准视图。显示为圆角药丸形,左侧为应用程序图标,右侧为系统图标。默认情况下,所有 Live Activities 以紧凑状态启动。
最小状态 在两个或多个任务同时活动时出现。Dynamic Island 「分裂」成相机左侧和右侧的两个独立元素。最小状态 允许显示两个独立的信息源,例如出租车到达时间和当前曲目。
扩展状态 通过长按 Dynamic Island 激活。在此模式下,显示带有可自定义内容的完整 widget:标题、描述、进度条、按钮。扩展状态支持滚动和交互元素。
ActivityKit — 在 iOS 16.1 中引入的 Swift 框架,允许应用程序在 Dynamic Island 和 Lock Screen 上发布 Live Activities。ActivityKit 使用基于 ActivityView 和 ActivityAttributes 的架构:前者定义内容类型,后者定义可变数据。该框架与 WidgetKit 协同工作,但与 widget 不同,Live Activities 可以在不打开应用程序的情况下实时更新。
import ActivityKit
import SwiftUI
// 定义活动属性
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var driverName: String
var distanceToArrival: Double
var estimatedMinutes: Int
}
var orderNumber: String
}
// 启动 Live Activity
func startDeliveryActivity() {
let initialState = DeliveryAttributes.ContentState(
driverName: "阿列克谢",
distanceToArrival: 3.5,
estimatedMinutes: 12
)
let attributes = DeliveryAttributes(orderNumber: "ORD-2024-8912")
let activity = try? Activity.request(
attributes: attributes,
contentState: initialState,
pushType: .token
)
}
Live Activities 通过 ActivityView 更新,它为 Dynamic Island 渲染 SwiftUI 内容。系统根据 Dynamic Island 的大小和活动数量自行决定使用哪个模板(紧凑、最小或扩展)。要更新内容,请调用 activity.update(using: contentState)。要结束 — activity.end(dismissalPolicy: .immediate)。
ActivityKit 支持通过 APNs(Apple Push Notification Service)进行 推送更新。在启动 Live Activity 时,您可以请求 pushToken 并从服务器发送更新,而无需在设备上运行应用程序。推送更新通过 activity.pushToken 和用于远程启动 Live Activity 的 Activity.pushToStartToken 工作。
// 通过推送更新 Live Activity
func updateActivity(activity: Activity<DeliveryAttributes>) {
let updatedState = DeliveryAttributes.ContentState(
driverName: "阿列克谢",
distanceToArrival: 1.2,
estimatedMinutes: 4
)
let alertConfiguration = AlertConfiguration(
title: "快递员已接近",
body: "阿列克谢将在 4 分钟内到达",
sound: .default
)
await activity.update(
using: updatedState,
alertConfiguration: alertConfiguration
)
}
AlertConfiguration — 一个附加参数,在重要更新时(例如「快递员已到达」)在 Dynamic Island 上方显示通知。没有 AlertConfiguration,内容会静默更新,适用于进度条和计时器。
Notch(刘海)— iPhone X–13 的硬件区域,包含前置摄像头、Face ID 传感器和扬声器。Notch 是静态的:其大小和形状不会改变,通知在其下方以标准横幅形式显示。相比之下,Dynamic Island 利用切口周围的像素显示内容,将硬件元素变成界面的一部分。
| 标准 | Dynamic Island | Notch |
|---|---|---|
| 交互性 | 支持点按、长按、滑动 | 不可交互 |
| 内容适应 | 根据上下文改变形状 | 静态,内容在刘海下方 |
| Live Activities | 通过 ActivityKit 内置支持 | 不支持 — 仅普通通知 |
| 多任务 | 两个同时活动(左侧和右侧) | 仅一个活动 |
| 可用性 | iOS 16.1+,iPhone 14 Pro 及更新机型 | iOS 11+,iPhone X–13 |
根据 Apple Human Interface Guidelines(2025),Dynamic Island 不得用于广告或持续显示静态内容。Live Activities 仅适用于具有明确生命周期的后台任务:计时器、配送、体育、音乐、导航。违反这些规则将导致应用在 App Store Review 中被拒绝。
Dynamic Island 具有严格的生命周期:活动通过 Activity.request() 请求开始,经过活动/暂停/更新状态,并以调用 activity.end() 结束。系统可以在内存不足时(例如启动相机时)强制结束活动。在这种情况下,应用程序通过 ActivityActivityState.finished 收到通知。
手势 Dynamic Island 由 ActivityView 内的 SwiftUI 内容处理。标准手势:点按紧凑状态打开应用程序,长按打开扩展状态,向下滑动关闭扩展状态。自定义手势通过活动视图内的 SwiftUI 修饰符(onTapGesture、onLongPressGesture)添加。
当系统结束 Live Activity(或用户通过滑动删除)时,应用程序应处理 finished 状态以释放资源。建议订阅 Activity.activityStateUpdates 并在完成后删除对活动的本地引用。
import ActivityKit
func observeActivityState(activity: Activity<DeliveryAttributes>) {
Task {
for await state in activity.activityStateUpdates {
switch state {
case .active:
print("Activity 在 Dynamic Island 上活跃")
case .dismissed:
print("Activity 已被用户隐藏")
await activity.end(dismissalPolicy: .immediate)
case .finished:
print("Activity 已被系统结束")
cleanupResources()
@unknown default:
break
}
}
}
}
Apple 建议(WWDC 2024,Session 10146):不要使用 Dynamic Island 显示不需要用户注意的状态。每个 Live Activity 应有明确的开始和结束触发器。对于无 UI 的后台更新,请使用 Background Tasks,而不是 Live Activities。
常见问题
Dynamic Island 适用于 iPhone 14 Pro、14 Pro Max 以及所有 iPhone 15 和 iPhone 16 型号(包括基础版本)。开发需要 iOS 16.1+ 和 Xcode 14.1。在较旧的型号(iPhone X–13)上使用不支持 Live Activities 的静态刘海。
Dynamic Island 将通知集成到屏幕的硬件区域,不会遮挡内容。普通通知以横幅形式出现在顶部,几秒钟后消失。Dynamic Island 上的 Live Activities 可以保持活动数小时并实时更新(配送状态、计时器、音乐)。
使用通过 APNs 的 推送更新。在启动 Live Activity 时,调用 activity.pushToken 并将令牌发送到您的服务器。服务器通过 APNs 发送带有新 ContentState 的更新请求。替代方案 — 从应用程序本身通过 activity.update(using:) 进行本地更新。
当有两个活动的 Live Activities 时,iOS 会自动将 Dynamic Island 分成两个段。每个活动以 最小状态 显示在相机的左侧和右侧。长按其中一个段时,仅打开该应用程序的扩展状态。
检查:(1)应用程序在 Info.plist 中有 NSSupportsLiveActivities = YES,(2)ActivityAttributes 和 ContentState 实现了 Codable 和 Hashable,(3)iOS 版本 16.1+,(4)设备支持 Dynamic Island。对于模拟器,在 Xcode 中使用 iPhone 14 Pro 或更新机型。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。