首页 > 解决方案 > 如何在 SwiftUI TabView 中保持滚动位置

问题描述

使用ScrollViewinside aTabView我注意到,当我在选项卡之间来回移动时,ScrollView 不会保持它的滚动位置。如何更改以下示例以使 ScrollView 保持其滚动位置?

import SwiftUI

struct HomeView: View {
    var body: some View {
        ScrollView {
            VStack {
                Text("Line 1")
                Text("Line 2")
                Text("Line 3")
                Text("Line 4")
                Text("Line 5")
                Text("Line 6")
                Text("Line 7")
                Text("Line 8")
                Text("Line 9")
                Text("Line 10")
            }
        }.font(.system(size: 80, weight: .bold))
    }
}

struct ContentView: View {
    @State private var selection = 0

    var body: some View {
        TabView(selection: $selection) {
            HomeView()
                .tabItem {
                    Image(systemName: "house")
                }.tag(0)

            Text("Out")
                .tabItem {
                    Image(systemName: "cloud")
                }.tag(1)
        }
    }
}

标签: swiftuitabview

解决方案


不幸的是,鉴于 SwiftUI (iOS 13.x/Xcode 11.x) 的当前限制,内置组件根本不可能做到这一点。

两个原因:

  1. 当您从选项卡切换离开时,SwiftUI 会完全处理您的视图。这就是您的滚动位置丢失的原因。它不像 UIKit,你有一堆屏幕外的 UIViewControllers。
  2. 没有ScrollView等价物UIScrollView.contentOffset。这意味着您无法将滚动状态保存在某处并在用户返回选项卡时恢复它。

您最简单的路线可能是使用一个UITabBarController用 s 填充UIHostingController的。这样,当用户在它们之间移动时,您就不会丢失每个选项卡的状态。

否则,您可以创建一个自定义选项卡容器,并自己修改每个选项卡的不透明度(而不是有条件地将它们包含在层次结构中,这是导致您当前问题的原因)。

var body: some View {
  ZStack {
    self.tab1Content.opacity(self.currentTab == .tab1 ? 1.0 : 0.0)
    self.tab2Content.opacity(self.currentTab == .tab2 ? 1.0 : 0.0)
    self.tab3Content.opacity(self.currentTab == .tab3 ? 1.0 : 0.0)
  }
}

当我想避免WKWebView每次用户短暂地离开时完全重新加载时,我就使用了这种技术。

我会推荐第一种技术。特别是如果这是您的应用程序的主要导航。


推荐阅读