Can somebody tell me if I'm doing something wrong or SwiftUI's scrollTo(id:anchor:) just doesn't work if the ScrollView is scrolling? I have a trivial example that demonstrates the issue:
import SwiftUI
@main struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct Item: Identifiable {
let id = UUID()
let timestamp: Date
let text: String
}
struct ContentView: View {
@State private var items: [Item] = (0...10_000).map{ .init(timestamp: Date(), text: "Row \($0)") }
@State private var scrollPosition = ScrollPosition(idType: Item.ID.self)
@State private var newMessage: String = ""
var body: some View {
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemView(item: item)
}
}.scrollTargetLayout()
}
.defaultScrollAnchor(.bottom, for: .initialOffset)
.scrollPosition($scrollPosition, anchor: .bottom)
.safeAreaBar(edge: .bottom) {
HStack {
TextField("Type here", text: $newMessage, axis: .vertical)
.textFieldStyle(.roundedBorder)
Button("Send", action: {
let trimmed = newMessage.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return }
newMessage = ""
items.append(.init(timestamp: .now, text: trimmed))
withAnimation(.smooth) {
scrollPosition.scrollTo(id: items.last!.id, anchor: .bottom)
}
})
}.padding()
}
}
}
struct ItemView: View {
let item: Item
var body: some View {
VStack(alignment: .leading) {
Text(item.text)
Text(item.timestamp.formatted())
}.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1)))
}
}
#Preview {
ContentView()
}
2
0
172