1.4 Landmarks:显示自定义活动徽章
原文链接: https://developer.apple.com/documentation/swiftui/landmarks-displaying-custom-activity-badges
1.4 Landmarks:显示自定义活动徽章
通过显示带动画的自定义活动徽章,给人们提供标记自己探险的方式。
概述
Landmarks 应用让人们探索世界各地的景点时记录自己的探险。无论是家附近的国家公园,还是另一个大陆上遥远的地点,这个应用都提供了一种方式来标记自己的探险,并沿途获得自定义的活动徽章。

这个示例把徽章显示在一个纵向视图中,该视图包含一个用于显示或隐藏徽章的切换按钮。Landmarks 应用包含一个自定义修饰符,让其他视图更容易采用徽章视图。通过把徽章配置为使用 Liquid Glass,你在显示或隐藏徽章时就能享受到形变动画的好处。
添加修饰符以便在其他视图中显示徽章
为了让徽章能在 CollectionsView 等其他视图中使用,示例使用了一个自定义修饰符 ShowBadgesViewModifier,作为 ViewModifier。示例用 ZStack 把徽章叠加在另一个视图之上,并把徽章视图定位到下方的后侧角落:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| private struct ShowsBadgesViewModifier: ViewModifier {
func body(content: Content) -> some View {
ZStack {
content
HStack {
Spacer()
VStack {
Spacer()
BadgesView()
.padding()
}
}
}
}
}
|
示例通过添加 showBadges 修饰符来扩展 View:
1
2
3
4
5
| extension View {
func showsBadges() -> some View {
modifier(ShowsBadgesViewModifier())
}
}
|
为创建切换按钮,示例用 ToggleBadgesLabel 配置了一个 Button,它针对「显示」和「隐藏」两种切换状态使用不同的系统图像。要应用 Liquid Glass,就用 glass 修饰符给按钮设置样式:
1
2
3
4
5
6
| Button {
//...
} label: {
//...
}
.buttonStyle(.glass)
|
给徽章添加 Liquid Glass
为了给每个徽章添加 Liquid Glass,示例使用了 glassEffect(_:in:) 修饰符。为做出自定义的玻璃外观,示例指定了带圆角半径的矩形选项:
1
2
| BadgeLabel(badge: $0)
.glassEffect(.regular, in: .rect(cornerRadius: Constants.badgeCornerRadius))
|
用形变效果给徽章添加动画
形变效果是 Liquid Glass 视图的一种动画。在这个动画过程中,切换按钮和每个徽章一开始是一个合并的视图。随后,按钮和徽章在分离并从一处移动到另一处时,像液体一样改变形状。反过来,切换按钮和各个徽章会改变形状并重新合并成一个视图。
为实现 Liquid Glass 形变效果,应用做了这些事:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| // 把各个徽章和切换按钮组织起来,让它们一起播放动画。
GlassEffectContainer(spacing: Constants.badgeGlassSpacing) {
VStack(alignment: .center, spacing: Constants.badgeButtonTopSpacing) {
if isExpanded {
VStack(spacing: Constants.badgeSpacing) {
ForEach(modelData.earnedBadges) {
BadgeLabel(badge: $0)
// 给徽章添加 Liquid Glass。
.glassEffect(.regular, in: .rect(cornerRadius: Constants.badgeCornerRadius))
// 给徽章添加一个用于动画的标识符。
.glassEffectID($0.id, in: namespace)
}
}
}
Button {
// 当 `isExpanded` 的值变化时,让这个按钮和徽章播放动画。
withAnimation {
isExpanded.toggle()
}
} label: {
ToggleBadgesLabel(isExpanded: isExpanded)
.frame(width: Constants.badgeShowHideButtonWidth,
height: Constants.badgeShowHideButtonHeight)
}
// 给按钮添加 Liquid Glass。
.buttonStyle(.glass)
#if os(macOS)
.tint(.clear)
#endif
// 给按钮添加一个用于动画的标识符。
.glassEffectID("togglebutton", in: namespace)
}
.frame(width: Constants.badgeFrameWidth)
}
|