从超级视图中删除滚动视图时触发重绘导航栏外观

Trigger redraw navigation bar appearance when scroll view is removed from superview

在iOS15中默认情况下,滚动到顶部时导航栏是透明的,然后向下滚动时显示其背景。如果它可以在视图层次结构中找到滚动视图,则此方法有效。

在我的应用中,用户可能会向下滚动导致导航栏背景可见,然后他们可以执行最终导致滚动视图从视图层次结构中删除的操作。问题是导航栏没有再次更新为透明。

如何在滚动视图从屏幕上移除后触发导航栏重绘?我试过了

navigationController?.navigationBar.scrollEdgeAppearance = nil
navigationController?.navigationBar.setNeedsDisplay()
navigationController?.navigationBar.setNeedsLayout()
navigationController?.navigationBar.layoutIfNeeded()

但不幸的是,这并没有起到作用 - 背景仍然可见。

我在 Twitter 上偶然发现了一个解决方案!感谢 tweeting 大卫·邓肯。

当滚动视图从视图层次结构中删除时,将其放入您的视图控制器中:

//update navigation bar appearance now that the scroll view is gone
setContentScrollView(UIScrollView(), for: .top)
setContentScrollView(nil, for: .top)

更新: 这在 iOS 15.0 beta 5 中有效,但此后一直无效,测试到 15.2。我提交了错误报告。

另一种解决方案是获取内容滚动视图并将其滚动到顶部,然后再将其从视图层次结构中删除:

if let scrollView = contentScrollView(for: .top) {
    scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: false)
}

这段代码似乎有效:

navigationController.map { nvc in
    nvc.navigationBar.isTranslucent.toogle()
    nvc.navigationBar.isTranslucent.toogle()
}