使用大标题时 iOS 11 滚动到顶部无法正常工作
Posted
技术标签:
【中文标题】使用大标题时 iOS 11 滚动到顶部无法正常工作【英文标题】:iOS 11 scroll to top when using large titles doesn't work properly 【发布时间】:2018-11-10 12:30:55 【问题描述】:当使用大标题并点击状态栏以滚动到UIScrollView
或UITableView
的顶部(可能还有UICollectionView
,尚未对此进行测试)时,它总是有点过头了。
我在TableView
上启用了刷新,当点击状态栏时,它会显示为这样并保持这种状态,直到我点击屏幕。
我在另一个ViewController
中有一个ScrollView
,如果我点击那里的状态栏,它也会滚动有点太远,使导航栏太高。当我点击某处或滚动一点点时,这也会恢复正常。
正常:
点击状态栏后:
这也只会在我激活大标题时发生,使用普通标题一切正常。
任何想法如何解决这个问题?
如何重新创建:
-
创建一个新项目,其中包含一个导航控制器和一个
UIViewController
,其中包含一个 TableView
。
将导航控制器设置为首选大标题。关闭半透明。在UIViewController
上设置标题
在TableView
上设置约束以固定到ViewController
的边缘
在ViewController
中为TableView
创建出口
实现委托并设置行数,例如 100
启动应用程序
向下滚动,使大标题变为普通标题
点击状态栏,tableView
滚动到顶部
现在标题不在应有的位置,如果您现在向上或向下滚动一点点,它会迅速回到正常位置。
ViewController
代码:
import UIKit
class ViewController: UIViewController
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad()
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
extension ViewController: UITableViewDelegate, UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 100
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath)
return cell
【问题讨论】:
我创建了一个新项目并放置了大标题并添加了一个刷新控件,在 TableView 中添加了 100 个项目,但我无法重现您的错误。 @Serj 哦,很奇怪,这并不是我在视图控制器中做了很多可能导致这种情况的原因,我会尝试找出我做错了什么,谢谢! 如果您可以为我们提供重现该错误的方法,我们将非常乐意提供帮助。这是有关如何执行此操作的指南***.com/help/mcve @Serj 添加了重新创建的步骤,从头开始,我仍然遇到同样的问题 @Fogmeister 添加(对于从头开始的新项目,因为它也在那里发生,不过它只是基本代码) 【参考方案1】:好的,所以我找到了问题发生的原因,但不知道如何在那个确切的情况下解决它。
如果您使用大标题和导航栏半透明设置为关闭的 UITableViewController,则会出现问题。 当您重新打开半透明时,问题就消失了。
如果您在普通 UIViewController 中使用 TableView,问题总是会发生。
编辑
事实证明,如果您使用的是半透明导航栏,设置“extendedLayoutIncludesOpaqueBars = true”可以解决问题!
类似问题:UIRefreshControl() in ios 11 Glitchy effect
【讨论】:
在普通的 UIViewController 中使用 tableView 有没有找到解决办法? @FrédéricAdda 请检查我的适用于 UIViewController 的答案【参考方案2】:我遇到了同样的问题。我在 UINavigationController 中嵌入了 UIViewController 中的 collectionview。 Collectionview 对安全区域有前导、尾随、顶部、底部约束。
要解决此问题,您需要:
-
将collectionview的top约束改为supervises(非安全区域)
在 viewDidLoad 方法中设置 extendedLayoutIncludesOpaqueBars = true
【讨论】:
稍微解决了这个问题,但完整的解决方案只是:self.tableView.scrollRectToVisible(CGRect(x: 0.0, y: 0.0, width: 1, height: 1), animated: true)
【参考方案3】:
经过数小时的测试,我找到了一个适用于 UIViewController 的解决方案。
在带有 UITableView 的 UIViewController 中,你应该:
在 viewDidLoad 中设置extendedLayoutIncludesOpaqueBars = true 在故事板中将 tableView 顶部约束到 superview 顶部,常量 = 0(当导航栏为半透明时,tableView 将位于导航栏和状态栏下)之后,如果你点击状态栏,tableview 会停在正确的位置。
【讨论】:
你检查过 iPhone X 吗?我需要针对安全区域设置 tableView 顶部约束。 @FrédéricAdda 是的,它有效。它也适用于不透明的导航栏(检查我编辑的答案)。为什么需要安全区域的顶部约束? 在我的情况下,我需要拉表视图重新加载。如果我在导航栏中使用“首选大字体”,则 tableView 不会滚动到顶部。如果我使用小字体,那么我没有问题。 @FrédéricAdda 在我的场景中,我也有 UIRefreshControl 并且运行良好。没有代码我帮不了你。还请记住,使用 largeTitle,您需要将 refreshControl 设置为 tableView.refreshControl 而不是 tableView.addSubview(refreshControl) 这段代码似乎可以正常工作,但是如果您不希望 TableView 被限制到 Superview,而是到另一个根据导航栏大小改变位置的 View,您会怎么做?【参考方案4】:在你的 ViewController 中声明一个 Bool 类型的 var didBeginScrollToTop。 将控制器分配为滚动视图的委托。那么
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool
didBeginScrollToTop = true
return true
func scrollViewDidScroll(_ scrollView: UIScrollView)
guard didBeginScrollToTop, scrollToTopGestureTargetView?.contentOffset.y ?? 0 < -25 else return
scrollToTopGestureTargetView?.setContentOffset(.zero, animated: true)
func scrollViewWillBeginDragging(_ scrollView: UIScrollView)
didBeginScrollToTop = false
这样做是在弹跳时调整您的内容偏移量。该标志用于捕捉 scrollToTop 手势并在滚动时重置。您也可以在设置 .zero 偏移后将其设置为关闭。如果你有子 VC 的实现,在覆盖这 3 个委托方法时不要忘记调用 super。 现在我的第一个方法是跟踪内容offSet 何时
请注意,您可能还需要处理:Strange velocity prefers large title
【讨论】:
【参考方案5】:我已经修复它,在滚动到顶部后将 contentOffset 设置为 0。
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool
return true
func scrollViewDidScrollToTop(_ scrollView: UIScrollView)
scrollView.contentOffset.y = 0.0
【讨论】:
与我之前看到的所有其他解决方案相比,您的解决方案似乎不那么老套。它运作良好吗?没有动画故障? 这并不理想,但可以工作。我的意思是在动画停止后一切正常,但是动画不是那么快,所以可以看出有些东西很丑。 这很笨拙。整整一秒钟后,它突然回弹并折叠我的搜索控制器搜索栏。 (iOS 13 Xcode 11.1)。不能推荐这个以上是关于使用大标题时 iOS 11 滚动到顶部无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
带有导航栏大标题的 UITableView 奇怪的滚动行为,顶部的弹跳效果在滚动到顶部时自动切断/生涩