Using Swift5.5, iOS15.0.1,
I had to realise that my circular ProgressBar does no longer animate after updating to iOS15.
Below is my code - can anybody tell me what to do in order to make the circular ProgressBar-View animate again ?
Can anybody tell me how to circumvent in this example the deprecation-warning
animation' was deprecated in iOS 15.0: Use withAnimation or animation(_:value:) instead.
?
import SwiftUI
struct ContentView: View {
@State var progressValue: Float = 0.28
var body: some View {
ProgressBar(progress: $progressValue)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ProgressBar: View {
@Binding var progress: Float
var body: some View {
ZStack {
Circle()
.stroke(lineWidth: 20.0)
.opacity(0.3)
.foregroundColor(Color.red)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 20.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.red)
.rotationEffect(Angle(degrees: 270.0))
.animation(.linear)
Text(String(format: "%.0f %%", min(self.progress, 1.0)*100.0))
.font(.largeTitle)
.bold()
}
}
}
My original version looked like this:
Circle()
.trim(from: 0, to: showFreespaceRing ? CGFloat(Double(freeDiskspace) / Double(totalDiskspace)) : 0)
.stroke(Color.green.opacity(0.7), style: StrokeStyle(lineWidth: 10, lineCap: .round))
.frame(width: circleDiam, height: circleDiam)
.animation(.easeIn(duration: 1))
.onAppear() {
showFreespaceRing = true
}
CodePudding user response:
The value
parameter takes an Equatable
that represents the value that is animating. In this case : progress
.
I also moved .animation
outside of the ZStack
-- otherwise, I was seeing a funny jitter on the animation.
struct ContentView: View {
@State var progressValue: Float = 0.28
let timer = Timer.publish(every: 1.0, on: .main, in: .default).autoconnect()
var body: some View {
ProgressBar(progress: $progressValue)
.onReceive(timer) { _ in
progressValue = 0.1
}
}
}
struct ProgressBar: View {
@Binding var progress: Float
var body: some View {
ZStack {
Circle()
.stroke(lineWidth: 20.0)
.opacity(0.3)
.foregroundColor(Color.red)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 20.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.red)
.rotationEffect(Angle(degrees: 270.0))
Text(String(format: "%.0f %%", min(self.progress, 1.0)*100.0))
.font(.largeTitle)
.bold()
}
.animation(.linear, value: progress)
}
}
CodePudding user response:
I finally found out was went wrong:
On my original version, I had
Circle()
.trim(from: 0, to: showFreespaceRing ? CGFloat(Double(freeDiskspace) / Double(totalDiskspace)) : 0)
.stroke(Color.green.opacity(0.7), style: StrokeStyle(lineWidth: 10, lineCap: .round))
.frame(width: circleDiam, height: circleDiam)
.animation(.easeIn(duration: 1))
.onAppear() {
showFreespaceRing = true
}
And now I have:
Circle()
.trim(from: 0, to: showFreespaceRing ? 0 : CGFloat(Double(freeDiskspace) / Double(totalDiskspace)))
.stroke(Color.green.opacity(0.7), style: StrokeStyle(lineWidth: 10, lineCap: .round))
.frame(width: circleDiam, height: circleDiam)
.animation(.easeIn(duration: 1), value: showFreespaceRing)
.onAppear() {
showFreespaceRing.toggle()
}
With this, the animation works again (somewhat - see video below, there is still one issue)....
The trick was to use .toggle()
inside the onAppear
method.
What definitively does not work is to have showFreespaceRing = true
inside the onAppear()
method (but rather showFreespaceRing.toggle()
instead !!!!!!!
And, of course, fulfilling iOS15's new value
inside animation
:
.animation(.easeIn(duration: 1), value: showFreespaceRing)
However, there is one annoyance, still, with the current solution:
THE ANIMATION IS NOT SMOOTH !!
See this video:
If you look carefully you can see that the animation is not smooth at all but rather flickering badly. (i.e. the ring-animation looks catastrophic, still). How can I get a smooth animation ??