我有一个进度视图,其进度/宽度可以设置为动画。该动画本身起作用。但是,在某些情况下,父视图会更改其布局,并在进度栏上方添加一个新视图。然后,进度视图下移以为新视图腾出空间。这也是动画。当两种动画都在iOS 13中发生时,进度视图将向下移动,同时蓝色进度条的宽度将被动画化。在iOS 14中,进度视图向下移动,但蓝色进度条也使用其动画为位置变化设置动画。在iOS 13中,它仅用于设置宽度的动画。这样会使动画看起来好像进度条会飞到进度视图中,这是错误的并且看起来很奇怪。
我使用以下代码复制了我在应用程序中拥有的代码。此代码也用于录制视频。
struct MainView: View {
@State var toggle = false
@State var trim: CGFloat = 0.2
var body: some View {
VStack {
Rectangle().frame(minHeight: 0, maxHeight: self.toggle ? 200 : 0)
ProgressBarView(trim: self.$trim)
Button(
action: {
withAnimation {
self.toggle.toggle()
self.trim = self.toggle ? 0.8 : 0.2
}
},
label: {
Text("Toggle")
})
}
}
}
struct ProgressBarView: View {
@State var grow: Bool = false
@Binding var trim: CGFloat
var body: some View {
ZStack(alignment: .leading) {
GeometryReader { geo in
Rectangle()
.opacity(0.1)
.zIndex(0)
Rectangle()
.frame(
minWidth: 0,
maxWidth: self.grow
? geo.frame(in: .global).width * self.trim
: 0
)
.animation(Animation.easeOut(duration: 1.2).delay(0.5))
.foregroundColor(Color(UIColor.systemBlue))
}
}
.cornerRadius(10)
.frame(height: 20)
.onAppear(perform: {
self.grow = true
})
}
}
更新
这是iPad上仍在运行iOS 13.7的原始代码,并且具有相同的代码。我只是消除了延迟并增加了使各种动画更加明显的时间。
更新2
回答问题时有些困惑,所以我复制了一些帧并将其放入屏幕截图中。我希望这有助于理解我的问题。左侧是iOS 14上的动画,具有不良行为。如您所见,某些图片中没有出现蓝色进度条。在其他图像中,它仅部分可见。右边是iOS 13动画。图像上的框架(以及所有其他框架)显示完全可见的蓝色进度条。它始终是完全可见的,并且位于背景的顶部。
我不了解iOS 14中的哪些更改(或者可能是Swift 5.3或其他任何更改)导致动画有所不同,并且找不到解决此问题的方法。
答案 0 :(得分:3)
嘿!我对ProgressBarView
结构进行了很少的更改。让我们首先了解不太重要的更改。
删除了GeometryReader
,并将其替换为screen.width
。如果要在容器内使用条形图以获得容器的宽度,请使用GeometryReader
。
将矩形更改为胶囊。
对重要的人
grow
struct ProgressBarView: View {
@State var grow: Bool = false
@Binding var trim: CGFloat
let screen = UIScreen.main.bounds
var body: some View {
VStack {
ZStack(alignment: .leading) {
Capsule()
.foregroundColor(Color.black.opacity(0.1))
Capsule()
.frame(width: self.grow ? screen.width * trim : 0)
.foregroundColor(.blue)
.animation(Animation.easeOut(duration: 1).delay(0.5), value: self.grow)
}
.frame(width: screen.width, height: 20)
.onAppear {
self.grow = true
}
}
}
}
更新1.1
ZStack
上添加了动画,以将bar从0初始增加到0.2 DispatchQueue
的延迟时间更改为0.18秒。延迟变化的原因是,由于矩形的扩展改变了条形图在y方向上的位置,因此将持续时间为1.2秒的动画效果应用于位置变化,不想要因此,延迟为0.18会在矩形展开后开始一点动画。这有点hack,但是可以完成工作。如果找到更好的解决方案,我将使用“ Update 2.0”更新此答案。如果您找到更好的解决方案,请告诉我。
代码
struct MainView: View {
@State var toggle = false
@State var trim: CGFloat = 0.2
var body: some View {
VStack {
Rectangle().frame(minHeight: 0, maxHeight: self.toggle ? 200 : 0)
ProgressBarView(trim: self.$trim)
Button(
action: {
withAnimation {
self.toggle.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.18) {
self.trim = self.toggle ? 0.8 : 0.2
}
}
},
label: {
Text("Toggle")
})
}
}
}
struct ProgressBarView: View {
@State var grow: Bool = false
@Binding var trim: CGFloat
let screen = UIScreen.main.bounds
var body: some View {
ZStack(alignment: .leading) {
Capsule()
.opacity(0.1)
Capsule()
.frame(width: self.grow ? screen.width * trim : 0)
.foregroundColor(.blue)
.animation(Animation.easeOut(duration: 1.2), value: self.trim)
}
.frame(width: screen.width, height: 20)
.onAppear {
self.grow = true
}
.animation(.easeOut(duration: 0.5), value: grow)
}
}
希望对您有帮助。