为 Group Activities 做设计
Design for Group Activities
2021年6月9日
一句话判断
这场 Session 不写一行代码,但它回答了一个比”怎么实现”更关键的问题——“怎么设计才能让用户愿意在 FaceTime 里一起用你的 App”。
这场 Session 讲了什么
Session 从设计角度讲解如何为 Group Activities(SharePlay)创建优秀的共享体验。不是 API 讲解,而是设计方法论——覆盖了共享场景的交互模式、UI 布局原则、以及常见的体验反模式。
核心设计原则是”共享但不打扰”(Shared but Not Intrusive)。用户在 FaceTime 中使用你的 App 时,视频通话界面占据了屏幕的顶部或侧边,你的 App 内容需要自适应剩余空间。Session 给出了三种布局模式:Side-by-side(并排模式,适合 iPad 和 Mac)、Picture-in-Picture(画中画模式,适合 iPhone)、和 Full Screen with Overlay(全屏叠加模式,视频窗口浮在内容上方)。Session 还讨论了”何时提示用户启动 SharePlay”的时机选择——不是每次打开 App 都弹提示,而是在用户明显处于社交场景时(比如刚加入 FaceTime 通话)才展示。
值得深挖的点
参与者状态的可视化设计
共享体验中,用户需要知道”其他人在做什么”。但把每个人的完整播放状态都展示出来会导致界面杂乱。Session 建议用”最小必要信息”原则:只展示参与者的头像和当前动作(播放/暂停/缓冲中),不展示详细进度。当某个参与者的操作影响了其他人时(比如暂停了共享的视频),用一个轻量的 toast 提示”某某暂停了视频”,3 秒后自动消失。
邀请流程的心理设计
邀请别人加入活动是一个敏感的社交动作——太突兀的邀请会让人不适。Session 建议邀请界面应该让发起者感到”我在分享好东西”而不是”我在打扰别人”。具体做法:邀请卡片上展示丰富的预览信息(电影海报、歌曲封面),而不是一行冷冰冰的文字。同时给发起者一个”先预览再发送”的确认步骤,减少”手滑发送”的尴尬。
代码片段
// 设计友好的 SharePlay 启动入口
// 不是每次打开 App 都弹邀请,而是在适当上下文中展示
struct MovieDetailView: View {
let movie: Movie
@Environment(\.supportsGroupActivities) var supportsGroupActivities
var body: some View {
VStack {
MoviePoster(movie: movie)
MovieInfo(movie: movie)
// 只在 FaceTime 通话中才显示 SharePlay 按钮
if supportsGroupActivities {
SharePlayButton(movie: movie)
.buttonStyle(.borderedProminent)
.padding()
}
}
}
}
struct SharePlayButton: View {
let movie: Movie
var body: some View {
Button {
Task {
let activity = WatchTogether(movie: movie)
try? await activity.activate()
}
} label: {
Label("一起看", systemImage: "shareplay")
.font(.headline)
}
}
}
// 适配 FaceTime 通话时的布局
struct AdaptivePlayerView: View {
@Environment(\.isGroupSessionActive) var isGroupSession
@State private var videoPlayer = AVPlayer()
var body: some View {
GeometryReader { geometry in
if isGroupSession && geometry.size.width > 800 {
// iPad / Mac:Side-by-side 布局
HStack {
VideoPlayer(player: videoPlayer)
.frame(width: geometry.size.width * 0.65)
// 聊天和参与者面板
VStack {
ParticipantsListView()
ChatView()
}
.frame(width: geometry.size.width * 0.35)
}
} else {
// iPhone:全屏视频,FaceTime 画中画浮在上层
ZStack(alignment: .topTrailing) {
VideoPlayer(player: videoPlayer)
// FaceTime 窗口由系统自动管理,无需手动布局
}
}
}
}
}
// 参与者操作的轻量提示
struct ParticipantToast: View {
let participantName: String
let action: String
var body: some View {
HStack(spacing: 8) {
Circle()
.fill(Color.blue)
.frame(width: 24, height: 24)
.overlay(Text(String(participantName.first!))
.font(.caption)
.foregroundStyle(.white))
Text("\(participantName) \(action)")
.font(.subheadline)
.foregroundStyle(.secondary)
}
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(.ultraThinMaterial, in: Capsule())
}
}
最佳实践
- SharePlay 的入口不要放在一级导航——把它藏在”分享”菜单或播放界面的工具栏中。只有用户处于 FaceTime 通话中时,才提升按钮的视觉权重。
- 参与者列表使用紧凑的水平排列(头像圆圈并排),而不是垂直列表——把更多空间留给内容本身。
- 当共享活动结束后(FaceTime 通话断开),不要立刻清空共享状态。保留内容让用户可以继续独自观看,只是不再同步。
还有什么值得关注
- Apple 的 Human Interface Guidelines 新增了 Group Activities 的设计指南章节,包含各种场景的布局模板。
- FaceTime 通话中的空间音频(Spatial Audio)会自动区分不同参与者的声音位置,你的 App 不需要额外处理。
- 在 tvOS 上,Group Activities 自动将 iPhone 作为遥控器——用户在 iPhone 上控制 tvOS 上的共享内容。