WWDC20: 在 Swift Playgrounds 中构建 SwiftUI 视图
发布
更新
字数
300
阅读
2 分钟
阅读量
571
WWDC 20 介绍了在 Playgrounds 中使用 SwiftUI 可以轻松构建原型或者在 Xcode 中使用的组件 https://developer.apple.com/videos/play/wwdc2020/10643/,过程比较简单,这里只记录了 ProgressView
部分的代码,稍有修改。
import SwiftUI
extension GeometryProxy {
var minSize: CGFloat {
min(size.width, size.height)
}
}
struct ProgressView: View {
let gradientColors: [Color] = [.pink, .purple]
let sliceSize = 0.35
let progress: Double
private let percentageFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .percent
return formatter
}()
private var strokeGradient: AngularGradient {
return AngularGradient(gradient: Gradient(colors: self.gradientColors), center: .center, angle: .degrees(-10))
}
init(_ progress: Double) {
self.progress = min(progress, 1)
}
var body: some View {
GeometryReader { geometry in
ZStack {
Group {
Circle()
.trim(from: 0, to: 1 - CGFloat(self.sliceSize))
.stroke(self.strokeGradient, style: self.strokeStyle(with: geometry))
.opacity(0.5)
Circle()
.trim(from: 0, to: (1 - CGFloat(self.sliceSize)) * CGFloat(self.progress))
.stroke(self.strokeGradient, style: self.strokeStyle(with: geometry))
}
.rotationEffect(.degrees(90) + .degrees(360 * self.sliceSize / 2))
if self.progress >= 0.995 {
Image(systemName: "star.fill")
.font(.system(size: 0.4 * geometry.minSize, weight: .bold, design: .rounded))
.foregroundColor(.yellow)
.offset(y: -0.05 * geometry.minSize)
.animation(nil, value: 0)
} else {
Text(self.percentageFormatter.string(from: self.progress as NSNumber)!)
.font(.system(size: 0.3 * geometry.minSize, weight: .bold, design: .rounded))
.offset(y: -0.05 * geometry.minSize)
.animation(nil, value: 0)
}
}
.offset(y: 0.1 * geometry.minSize)
}
.padding(40)
.background(Color(uiColor: .systemBackground))
.cornerRadius(20)
}
private func strokeStyle(with geometry: GeometryProxy) -> StrokeStyle {
return StrokeStyle(lineWidth: 0.12 * geometry.minSize, lineCap: .round)
}
}
fileprivate struct Preview: View {
@State var progress = 0.25
var body: some View {
VStack {
ProgressView(progress)
}
.onTapGesture {
increment()
}
.padding(50)
.background(Color(uiColor: UIColor.secondarySystemBackground))
}
func increment() {
withAnimation {
progress += 0.1
}
}
}
struct Preview_Previews: PreviewProvider {
static var previews: some View {
Preview()
}
}