I want the ScrollView to scroll to top when I tap on the tab. It works but it stops parallel to the navigation title and doesn’t scroll all the way below the title as expected.
The current behaviour is,
1st tap: scrolls parallel to the navigation title (Image 1)
tap again: scrolls below nav title as expected (Image 2)
This is a poc of a much larger code so using a ListView is not an option.
struct Tabs {
static let One = "1"
static let Two = "2"
static let Three = "3"
}
struct ContentView: View {
@State var scrollToTop = false
@State private var currentTab: String = Tabs.One
var body: some View {
TabView(selection: tabSelection) {
TestView(scrollToTop: $scrollToTop)
.tabItem {
Label("First", systemImage: "1.circle")
}.tag(Tabs.One)
}
}
var tabSelection: Binding<String> {
Binding( get: {
currentTab
}, set: { newValue in
/// Tapped on the same tab.
if newValue == currentTab {
switch newValue {
case Tabs.One:
scrollToTop = true
case Tabs.Two:
print(newValue)
case Tabs.Three:
print(newValue)
default:
return
}
}
currentTab = newValue
})
}
}
struct TestView: View {
@Binding var scrollToTop: Bool
var body: some View {
NavigationView {
ScrollView {
ScrollViewReader { proxy in
LazyVStack {
Text("Text 0")
.id(0)
// Simulating other views (these views will be added manually in the real app without the ForEach)
ForEach(0...50, id: .self) { index in
Text("Text (index)")
}
}
.navigationTitle("Title")
.onChange(of: scrollToTop) {
if scrollToTop {
withAnimation { // works without withAnimation only if scroll is not ongoing.
proxy.scrollTo(0)
// proxy.scrollTo(0, anchor: .bottom) doesn't work with any anchor as well
}
scrollToTop = false
}
}
}
}
}
}
}
tried setting anchor of scrollTo, not working
tried without withAnimation. This works (although it’s ugly) if scrolling is not ongoing. If you tap the tab while scroll is still happening the behaviour is even stranger.