I've got a simple chat view that scrolls up to reveal new messages that appear at the bottom of the chat. What's weird is that sometimes, the duration of the scroll animation is much longer than normal.
I think it happens when a message comes in while the animation is still underway.
My code looks like this:
struct
OverlayChatView: View
{
@ObservedObject public var stream : ChatStream
var body: some View {
ScrollViewReader { scrollView in
ScrollView {
LazyVStack(alignment: .leading, spacing: 0.0) {
ForEach(self.stream.messages) { inMsg in
ChatMessageCell(message: inMsg)
}
.onChange(of: self.stream.messages, perform: { inMessages in
if inMessages.count < 1 { return }
withAnimation(.linear(duration: 0.25)) {
scrollView.scrollTo(inMessages.last!.id, anchor: .bottom)
}
})
.padding(8)
}
}
}
}
}
self.stream
is passed in from an @ObservedObject
ChatStream
with a simple Timer inserting a new message every 5.0 seconds. If the interval is 2.0 seconds, then it just continually scrolls upward slowly.
One other thing I notice is that .onChange()
gets called three times for each insert. Perhaps my ChatStream
is doing something dumb. I mention it because just invoking the animation three times in quick succession doesn't cause the slowdown. It seems more related to where the scroll is currently vs where it has to go.
Any idea how I can avoid this slowdown?
We will explore a ScrollView, UIScrollView equivalent in SwiftUI. List view is a view that contains child views and displays them in a scrollable manner. SwiftUI offers two views with this capability, ScrollView and List. In the previous post, we learned two ways to populate a list view's content.
By default, the scroll view will create with a vertical scrolling direction. To make a scroll view scroll horizontally, you passing Axis.Set.horizontal as axes argument. <1> Set axes as .horizontal to enable horizontal scrolling. <2> We use HStack instead of VStack here to align our child views horizontally.
The default behavior of View will simply layout them vertically, which is not scrollable. In this article, we will visit one of a list view, ScrollView. You can easily support sarunw.com by checking out this sponsor. Turn your code into a snapshot: Codeshot creates a beautiful image of your code snippets. Perfect size for Twitter. Get it now!
List view is a view that contains child views and displays them in a scrollable manner. SwiftUI offers two views with this capability, ScrollView and List. In the previous post, we learned two ways to populate a list view's content.
I ran into this bug when testing my app for iOS 14 (the issue seems to have been fixed in iOS 15).
The solution I found is to just wrap the withAnimation call within a main thread async call, like so:
DispatchQueue.main.async {
withAnimation(.linear(duration: 0.25)) {
scrollView.scrollTo(inMessages.last!.id, anchor: .bottom)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With