Reputation: 817
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
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