我一直在试验一些 SwiftUI 布局,我想尝试的其中一件事是创建一个简单的圆形进度环。玩了一会儿代码后,我设法让一切都按照我希望的方式工作,至少对于原型(prototype)来说是这样。当我将此 View 嵌入到 SwiftUI NavigationView 中时,问题就出现了。现在,每次我在 Canvas 、模拟器或设备上运行该应用程序时,进度环的初始加载都会使整个 View 缓慢向上滑动到位。
这是一个简单的原型(prototype),只是在摆弄新的 SwiftUI 工具。经过一些实验,我发现如果我删除 NavigationView,环的行为就像它从一开始就意味着的那样。不过,我没有看到出现此问题的明显原因。
import SwiftUI
struct ProgressRing_ContentView: View {
@State var progressToggle = false
@State var progressRingEndingValue: CGFloat = 0.75
var ringColor: Color = Color.green
var ringWidth: CGFloat = 20
var ringSize: CGFloat = 200
var body: some View {
TabView{
NavigationView{
VStack{
Spacer()
ZStack{
Circle()
.trim(from: 0, to: progressToggle ? progressRingEndingValue : 0)
.stroke(ringColor, style: StrokeStyle(lineWidth: ringWidth, lineCap: .round, lineJoin: .round))
.background(Circle().stroke(ringColor, lineWidth: ringWidth).opacity(0.2))
.frame(width: ringSize, height: ringSize)
.rotationEffect(.degrees(-90.0))
.animation(.easeInOut(duration: 1))
.onAppear() {
self.progressToggle.toggle()
}
Text("\(Int(progressRingEndingValue * 100)) %")
.font(.largeTitle)
.fontWeight(.bold)
}
Spacer()
Button(action: {
self.progressRingEndingValue = CGFloat.random(in: 0...1)
}) { Text("Randomize")
.font(.largeTitle)
.foregroundColor(ringColor)
}
Spacer()
}
.navigationBarTitle("ProgressRing", displayMode: .inline)
.navigationBarItems(leading:
Button(action: {
print("Refresh Button Tapped")
}) {
Image(systemName: "arrow.clockwise")
.foregroundColor(Color.green)
}, trailing:
Button(action: {
print("Share Button Tapped")
}) {
Image(systemName: "square.and.arrow.up")
.foregroundColor(Color.green)
}
)
}
}
}
}
#if DEBUG
struct ProgressRing_ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ProgressRing_ContentView()
.environment(\.colorScheme, .light)
.previewDisplayName("Light Mode")
}
}
#endif
以上是我目前正在使用的确切代码。环滑动的实际动画似乎按照我的预期工作,我只是不确定为什么当嵌入 NavigationView 时整个环本身都在移动。
最佳答案
您需要使用显式动画,而不是隐式动画。使用隐式动画,任何更改的动画参数,框架都会动画。只要有可能,您应该使用明确的动画。下面是更新后的代码。请注意,我删除了 .animation() 调用并添加了两个 withAnimation() 闭包。
如果您想扩展关于隐式动画与显式动画的知识,请查看此链接:https://swiftui-lab.com/swiftui-animations-part1/
struct ContentView: View {
@State var progressToggle = false
@State var progressRingEndingValue: CGFloat = 0.75
var ringColor: Color = Color.green
var ringWidth: CGFloat = 20
var ringSize: CGFloat = 200
var body: some View {
TabView{
NavigationView{
VStack{
Spacer()
ZStack{
Circle()
.trim(from: 0, to: progressToggle ? progressRingEndingValue : 0)
.stroke(ringColor, style: StrokeStyle(lineWidth: ringWidth, lineCap: .round, lineJoin: .round))
.background(Circle().stroke(ringColor, lineWidth: ringWidth).opacity(0.2))
.frame(width: ringSize, height: ringSize)
.rotationEffect(.degrees(-90.0))
.onAppear() {
withAnimation(.easeInOut(duration: 1)) {
self.progressToggle.toggle()
}
}
Text("\(Int(progressRingEndingValue * 100)) %")
.font(.largeTitle)
.fontWeight(.bold)
}
Spacer()
Button(action: {
withAnimation(.easeInOut(duration: 1)) {
self.progressRingEndingValue = CGFloat.random(in: 0...1)
}
}) { Text("Randomize")
.font(.largeTitle)
.foregroundColor(ringColor)
}
Spacer()
}
.navigationBarTitle("ProgressRing", displayMode: .inline)
.navigationBarItems(leading:
Button(action: {
print("Refresh Button Tapped")
}) {
Image(systemName: "arrow.clockwise")
.foregroundColor(Color.green)
}, trailing:
Button(action: {
print("Share Button Tapped")
}) {
Image(systemName: "square.and.arrow.up")
.foregroundColor(Color.green)
}
)
}
}
}
}
关于swift - 是什么导致了 SwiftUI 和 NavigationView 的这个动画错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57737144/