Reputation: 985
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 on tab: 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(1...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.
Upvotes: 1
Views: 244
Reputation: 185
The id you wrote in Foreach and the id of Text("Text 0") have the same ids, so you can change one of these ids and fix it according to which one you want to be unique.
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)")
}
Upvotes: 0