Back again for some SwiftUI issues. haha
So I have a scroll view, and I simulate a user switching elements in the scrollview pretty fast.
(ex. Music Lyrics that adjust to where the user is listening).
My issue here is the animation are not following the speed and I was wondering if there was a way to prevent that. Cancel the previous animation for example? I haven't found anything atm to fix this problem.
The following code is used to reproduce the Animation issue.
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
ScrollView(showsIndicators: false, content: {
ScrollViewReader(content: { scrollViewProxy in
LazyVStack(content: {
ForEach(viewModel.fragments, id: .id) { fragment in
Text(fragment.content + fragment.id)
.background(fragment == viewModel.currentFragment ? Color.yellow : Color.gray)
.frame(height: 100)
.font(.largeTitle)
.id(fragment.id)
}
})
.id("ContentView-LazyVStack-Animation")
.onReceive(viewModel.$currentFragment, perform: { currentFragment in
guard let currentFragment = currentFragment else {
return
}
withAnimation(.easeInOut(duration: 2)) {
scrollViewProxy.scrollTo(currentFragment.id, anchor: .center)
}
})
})
})
.id("ContentView-ScrollView-Animation")
}
}
final class ViewModel: ObservableObject {
@Published var fragments: [Fragment] = [Int](0..<100).map({ Fragment(id: "($0)", content: "Some text yeah! super cool.") })
@Published var currentFragment: Fragment?
private var scrollingTimer: Timer?
init() {
currentFragment = fragments.first
setupRandomScroll()
}
func setupRandomScroll() {
scrollingTimer = Timer.scheduledTimer(withTimeInterval: 0.2,
repeats: true,
block: { [weak self] _ in
guard let self = self else {
return
}
let newIndex = Int.random(in: 70..<100)
self.currentFragment = self.fragments[newIndex]
})
}
}
final class Fragment: ObservableObject, Equatable, Hashable {
var id: String
@Published var content: String
init(id: String, content: String) {
self.id = id
self.content = content
}
static func == (lhs: Fragment, rhs: Fragment) -> Bool {
return lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
Thanks in advance for any help given! :)
question from:
https://stackoverflow.com/questions/65931284/swiftui-scrollview-not-following-the-chained-animation 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…