Arnav Motwani
Arnav Motwani

Reputation: 817

Animated view floats into place weirdly SwiftUI

So I have a circular progress bar that is declared like this

struct ProgressBar: View {
    var progress: CGFloat
    var body: some View {
        let gradient = LinearGradient(...)
        ZStack {
            Circle()
                .stroke(lineWidth: 25)
                .opacity(0.3)
                .foregroundColor(Color.secondary)
            
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
                .stroke(gradient ,style: StrokeStyle(lineWidth: 25.0, lineCap: .round, lineJoin: .round))
                .rotationEffect(Angle(degrees: 270.0))
                .animation(.linear)
        }
    }
}

The variable progress is passed into the view and is just simple division of value/total where I have two buttons to reduce or increase value and I use the animation to update the progress cleanly.

I call this view in another view called DetailView

However for some reason the second secondView floats in from the top when I navigate to DetailView from another view. What is happening?

Im not sure if this is a common issue but I can share a video if that might help you.

As requested here is an example.


import SwiftUI

struct ContentView: View {
    
    @State var bookData: [Book] = load("list")
    @State private var selectedBook: Book? = nil
    @State var showOnboarding = false
    var body: some View {
        NavigationView {
                Form {
                    Section{
                        ForEach(bookData){ bookDetail in
                            NavigationLink(
                                destination: PageDetail(bookData: $bookData, book: bookDetail),
                                label: {
                                    BookView(book: bookDetail)
                                })
                                }
                        }
             }
      }
}
import SwiftUI

struct PageDetail: View {
    
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @Binding var bookData: [Book]
    @State var count = 0
    
    var progress: CGFloat{
        let page = value
        let total = Int(book.total) ?? 1
        
        let answer = CGFloat(page)/CGFloat(total)
        return answer
    }
    var value: Int{
        let page = Int(book.page) ?? 1
        let cnt = count
        let calc = page + cnt
        return calc
    }

    var book: Book{
    
    var body: some View {
        ZStack{
            LinearGradient(...)
            
            VStack {
                VStack(spacing: -25){
                    ProgressBar(page: value,total: book.total ,progress: progress)
                        .frame(width: 250, height: 300)
                        .padding(.horizontal, 20)
                    HStack {
                        Button(action: {
                            self.count -= 1
                        }, label: {
                            Image(systemName: "minus.circle")
                        })


                        Button(action: {
                            self.count += 1
                        }, label: {
                            Image(systemName: "plus.circle")
                        })

                    }
                }
                
            }
        }
}
struct ProgressBar: View {
    var page: Int
    var total: String
    var progress: CGFloat
    var body: some View {
        let gradient = LinearGradient(...)
        ZStack {
            Circle()
                .stroke(lineWidth: 25)
                .opacity(0.3)
                .foregroundColor(Color.secondary)
            
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
                .stroke(gradient ,style: StrokeStyle(lineWidth: 25.0, lineCap: .round, lineJoin: .round))
                .rotationEffect(Angle(degrees: 270.0))
                .animation(.linear)
        }
    }
}

struct PageDetail_Previews: PreviewProvider {
    @State static var previewed = testData
    static var previews: some View {
        PageDetail(bookData: $previewed, book: previewed[0])
    }
}

Upvotes: 1

Views: 447

Answers (1)

Asperi
Asperi

Reputation: 257729

Only idea - try to make animation value dependent, like below

Circle()
    .trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
    .stroke(gradient ,style: StrokeStyle(lineWidth: 25.0, lineCap: .round, lineJoin: .round))
    .rotationEffect(Angle(degrees: 270.0))
    .animation(.linear, value: progress)    // << here !!

Upvotes: 3

Related Questions