0

In xCode 11.4 the circle animation was behaving correctly. It was causing a delay in the progress ring (the circle inside the border) a few seconds after the bottom sheet was presented. Now it is delaying the presentation of the entire circle in Xcode 13.2.

Here is full code example with a video example: https://github.com/SimonSays1993/SwiftUI_Part2/blob/main/README.md

In a short summary, this is what's currently happening.

In another view, there is a card, and when I tap on it I toggle a state which displays a bottom sheet. This state then gets passed to the BottomSheetView and then to RingView through Binding.

We then use this value to display the RingView. The RingView has a delay animation base on the Binding variable show. This works fine in presenting the CircleView, but the problem is when the RingView appears I toggle a state to become true to then try and start the animation of the second Circle (call this progress ring) inside the border view of the circle.

Every time the RingView appears the progress ring is already loaded, and its delayed animation is not working.

struct RingView: View {
    var color1 = Color.red
    var color2 = Color.purple
    var width: CGFloat = 88
    var height: CGFloat = 88
    var percent: CGFloat = 88
    
    @Binding var show: Bool
    @State var progressCircle: Bool = false

    var body: some View {
        let multiplier = width / 44
        let progress = 1 - (percent / 100)
        
        return ZStack {
            //The grey border circle
            Circle()
                .stroke(Color.black.opacity(0.1), style: StrokeStyle(lineWidth: 5 * multiplier))
                .frame(width: width, height: height)
            
            Circle()
                .trim(from: progressCircle ? progress : 1, to: 1)
                .stroke(style: StrokeStyle(lineWidth: 5 * multiplier, lineCap: .round))
                .rotationEffect(Angle(degrees: 90))
                .rotation3DEffect(Angle(degrees: 180), axis: (x: 1, y: 0, z: 0))
                .frame(width: width, height: height)
                .animation(.linear.delay(2.0), value: progressCircle)
            
            Text("\(Int(percent))%")
                .font(.system(size: 14 * multiplier))
                .fontWeight(.bold)
        }
        .animation(.linear.delay(1.5), value: show)
        .onAppear {
            self.progressCircle.toggle()
        }
    }
}
Simon McNeil
  • 293
  • 1
  • 13
  • 1
    With a [mre], you are much more likely to receive useful help. What you've included won't compile because of missing code. – jnpdx Jan 13 '22 at 17:10
  • @jnpdx updated the code with a minimal reproducible example – Simon McNeil Jan 13 '22 at 17:30
  • Warnings about deprecated `animation` calls need to be fixed. For example, the first should probably be `.animation(.timingCurve(0.2, 0.8, 0.2, 1, duration: 0.8), value: showBottomCard)`. I don't think the example mutates the progress, so I'm not sure what the second will end up being (right now, it can just be commented out). – jnpdx Jan 13 '22 at 17:37
  • What OS version are you targeting? I am presuming you meant this worked with Xcode 11.4, not iOS 11.4 since that predated SwiftUI. One thing I notice is that you are using the deprecated `Animation()` init. You should be using `Animation( ,value:)` init. Lastly, that is not a minimal example. – Yrb Jan 13 '22 at 17:37
  • @Yrb I've updated my question and use the new animation. I hope my question is more clear now. – Simon McNeil Jan 13 '22 at 20:25

1 Answers1

0

Solved my answer, I needed to add a longer delay for the progress ring circle. Thanks for the commentators in my post that told me about the new Animation() init

struct RingView: View {
    var color1 = Color.red
    var color2 = Color.purple
    var width: CGFloat = 88
    var height: CGFloat = 88
    var percent: CGFloat = 88
    
    @Binding var show: Bool
    @State var progressCircle: Bool = false
    
    var body: some View {
        let multiplier = width / 44
        let progress = 1 - (percent / 100)
        
        return ZStack {
            //Inactive String, the grey circle
            Circle()
                .stroke(Color.black.opacity(0.1), style: StrokeStyle(lineWidth: 5 * multiplier))
                .frame(width: width, height: height)
            
            Circle()
                .trim(from: progressCircle ? progress : 1, to: 1)
                .stroke(style: StrokeStyle(lineWidth: 5 * multiplier, lineCap: .round))
                .rotationEffect(Angle(degrees: 90))
                .rotation3DEffect(Angle(degrees: 180), axis: (x: 1, y: 0, z: 0))
                .frame(width: width, height: height)
                .animation(.linear(duration: 1.0).delay(2.0), value: progressCircle)
            
            Text("\(Int(percent))%")
                .font(.system(size: 14 * multiplier))
                .fontWeight(.bold)
        }
        .animation(.linear.delay(0.5), value: show)
        .onAppear {
            self.progressCircle.toggle()
        }
    }
}
RTXGamer
  • 3,215
  • 6
  • 20
  • 29
Simon McNeil
  • 293
  • 1
  • 13