单击内部选项卡时保持 ScrollView 位置(其中刷新内部数据)

Keep ScrollView position when clicking a tab inside (which refresh data inside)

滚动视图 - 内容视图 - 1) 图像,2) 选项卡,3) 堆栈视图

以上是我的分镜安排。 选项卡实际上是集合视图。选项卡下方,有堆栈视图 (也在内容视图中)。当我单击每个选项卡时,我 将所选选项卡的索引 发送到 didSelect。它将调用具有以下流程的 refreshData 函数:堆栈视图 中的 当前子视图 将被删除 (使用 vc.mainStack.subviews.forEach({ $0.removeFromSuperview() })) 并将 根据索引 重新加载另一个子视图所选选项卡的。图片的位置将保持不变,即页面顶部。但是,每次我单击该选项卡时,屏幕总是会滚动到顶部。如何保持滚动位置(在我点击另一个标签之前),以便当我点击新标签时,它会保持在相同的滚动位置?

self.yContentOffset = scrollView.contentOffset.y

已经在 scrollViewDidScroll 中添加了上面的代码并且

vc.scrollView.contentOffset.y = self.yContentOffset

删除堆栈中的所有子视图后添加上面的代码,然后我调用新数据(用于子视图)。还尝试在调用新子视图后添加代码,但两者都不起作用。有谁知道如何做到这一点的逻辑?

听起来问题是 UI 在您删除当前子视图和添加新子视图之间 "refreshed"。因此,您的 mainStack 变得非常短,导致内容视图不够高,无法滚动,您的滚动视图会相应地自行调整。

您的选择是等待删除子视图,直到您有新的子视图,然后删除/添加相同的功能,或者用清晰的 "placeholder" 视图替换子视图。

第二个选项可能如下所示:

func replaceViewsWithPlaceholderView() -> Void {

    // get an array of the current views in the stack
    let viewsToRemove = mainStack.arrangedSubviews

    // create a clear view
    let v = UIView()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.backgroundColor = .clear

    // needs a width
    v.widthAnchor.constraint(equalToConstant: 1).isActive = true

    // constrain the height of the "place holder" view to the current height of the stack view
    v.heightAnchor.constraint(equalToConstant: mainStack.frame.height).isActive = true

    // add the "place holder" view to the stack
    mainStack.addArrangedSubview(v)

    // remove the views that were in the stack
    viewsToRemove.forEach {
        [=10=].removeFromSuperview()
    }

}

然后在根据所选选项卡添加新子视图的函数中,首先:

    // remove the "place holder" view
    mainStack.arrangedSubviews.forEach {
        [=11=].removeFromSuperview()
    }

接着(可能是 .forEach 循环)将新的子视图添加到 main.Stack

当然,如果您已经滚动,所以您的 "tabs" 位于滚动视图的顶部,并且 "tab B" 没有足够的子视图需要滚动,滚动视图将再次调整- 但仅限于内容视图底部位于滚动视图底部的位置。