SwiftUI实现Apple Game Center风格圆形成就视图
SwiftUI 实现 Game Center 风格圆形成就视图
核心思路
解决环形文本对齐和弧线标题的关键是利用几何计算定位字符和路径文本渲染,替代单纯的旋转Text视图。下面分组件实现,再整合为完整视图。
1. 顶部环形排列文本
通过拆分文本为单个字符,结合几何计算确定每个字符的旋转角度和位置,确保字符沿环形均匀分布且朝向正确:
struct CircularTopText: View { let text: String let radius: CGFloat let fontSize: CGFloat var body: some View { GeometryReader { geo in ZStack { ForEach(Array(text.enumerated()), id: \.offset) { index, char in Text(String(char)) .font(.system(size: fontSize, weight: .bold)) .foregroundColor(.white) .position( x: geo.size.width / 2 + radius * cos(angleForIndex(index)), y: geo.size.height / 2 + radius * sin(angleForIndex(index)) ) .rotationEffect(Angle(radians: angleForIndex(index) + .pi / 2)) } } } } private func angleForIndex(_ index: Int) -> Double { let totalChars = text.count let anglePerChar = 2 * Double.pi / Double(totalChars) // 让文本从顶部开始排列,调整起始角度 return anglePerChar * Double(index) - Double.pi / 2 } }
2. 中心弧线环绕标题
iOS 16+ 可直接利用AttributedString的路径属性实现文本沿弧线排列,这里给出原生SwiftUI方案:
struct ArcTitle: View { let title: String let arcRadius: CGFloat let fontSize: CGFloat var body: some View { GeometryReader { geo in Text(attributedTitle) .position(x: geo.size.width / 2, y: geo.size.height / 2) } } private var attributedTitle: AttributedString { var attrString = AttributedString(title) attrString.font = .system(size: fontSize, weight: .semibold) attrString.foregroundColor = .white // 创建弧形路径,调整弧度让文本向上弯曲 let path = CGMutablePath() path.addArc(center: .zero, radius: arcRadius, startAngle: .pi * 0.75, endAngle: .pi * 1.25, clockwise: false) attrString.path = path return attrString } }
3. 完整成就视图整合
将两个组件与背景、中心图标等整合,形成最终效果:
struct GameCenterAchievementView: View { var body: some View { ZStack { // 成就背景圆 Circle() .fill(LinearGradient(gradient: Gradient(colors: [.blue, .purple]), startPoint: .topLeading, endPoint: .bottomTrailing)) .frame(width: 300, height: 300) // 顶部环形文本 CircularTopText(text: "COMPLETE ALL CHALLENGES", radius: 130, fontSize: 12) // 中心弧线标题 ArcTitle(title: "MASTER COLLECTOR", arcRadius: 80, fontSize: 18) // 中心图标示例 Image(systemName: "trophy.fill") .font(.system(size: 60)) .foregroundColor(.yellow) } } } // 预览 struct GameCenterAchievementView_Previews: PreviewProvider { static var previews: some View { GameCenterAchievementView() } }
关键调整说明
- 环形文本通过
angleForIndex计算每个字符的弧度,确保从顶部开始均匀分布,旋转效果让字符始终朝向外侧 - 弧线标题通过调整
addArc的起始/结束角度,控制文本的弯曲方向和覆盖范围 - 所有组件使用
GeometryReader适配容器大小,避免硬编码位置导致的适配问题
内容的提问来源于stack exchange,提问作者Codelaby
相关产品推荐
相关产品推荐

