Текущее поведение:
1-е нажатие на вкладку: прокручивается параллельно заголовку навигации (изображение 1).
Нажмите еще раз: прокручивается под заголовком навигации, как и ожидалось. (Изображение 2)
Это фрагмент гораздо более крупного кода, поэтому использование ListView недопустимо.


Код: Выделить всё
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 {
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
}
}
}
}
}
}
}
пробовал без withAnimation. Это работает (хотя и некрасиво), если прокрутка не происходит. Если вы коснетесь вкладки во время прокрутки, поведение будет еще более странным.
Подробнее здесь: https://stackoverflow.com/questions/786 ... way-to-top
Мобильная версия