swift - 滚动到顶部时,UIScrollView 出现故障和抖动
问题描述
我有一个UIViewController
包含一个UICollectionView
和一个UIView
作为视图标题的。
我想在视图滚动时折叠标题。我目前正在通过在变量中捕获我的标题的顶部锚点并使用scrollViewDidScroll
来设置constant
该值来执行此操作。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
headerTopAnchor.constant = max(-headerView.frame.height, -scrollView.contentOffset.y)
}
这是有效的,因为集合视图向上滚动,标题滚动到屏幕外,反之亦然。
但是,如果集合视图中的内容不太适合 - 如果只有半个左右的单元格滚动到屏幕外,则会出现奇怪的颤抖行为。
如果我向其中添加打印语句,scrollViewDidScroll
我可以看到集合视图过度滚动了少量,这导致顶部锚点多次少量更改
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(max(-headerView.frame.height, -scrollView.contentOffset.y))
headerTopAnchor.constant = max(-headerView.frame.height, -scrollView.contentOffset.y)
}
我怎样才能防止这种行为?
我已经包含了一个应该演示问题的视图控制器 -
final class TestViewController: UIViewController {
private let headerView: UIView = {
let view = UIView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .systemTeal
return view
}()
private(set) lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .clear
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
return collectionView
}()
private lazy var headerTopAnchor = NSLayoutConstraint()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGray
[headerView, collectionView].forEach(view.addSubview(_:))
NSLayoutConstraint.activate([
headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
headerView.heightAnchor.constraint(equalToConstant: 180),
collectionView.topAnchor.constraint(equalTo: headerView.bottomAnchor),
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
headerTopAnchor = headerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
headerTopAnchor.isActive = true
}
}
extension TestViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return 300 // no problem
return 10 // problem :(
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
cell.backgroundColor = indexPath.item % 2 == 0 ? .darkGray : .lightGray
return cell
}
}
extension TestViewController: UICollectionViewDelegateFlowLayout {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(max(-headerView.frame.height, -scrollView.contentOffset.y))
headerTopAnchor.constant = max(-headerView.frame.height, -scrollView.contentOffset.y)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: collectionView.frame.width, height: 60)
}
}
解决方案
似乎UIScrollView
有一个默认bounces
设置为的属性。true
从文档中:
如果此属性的值为 true,则滚动视图在遇到内容边界时会弹跳。在视觉上弹跳表示滚动已到达内容的边缘。如果该值为 false,则滚动立即在内容边界处停止而不弹跳。默认值是true。
这解释了在应用动画的同时在到达边界时被顶部约束纠正时的颤抖行为。
我设置collectionView.bounces = false
了viewDidLoad
它,它现在按预期工作。
推荐阅读
- python - 如果您在读取 csv 文件后 seek(0),则 line_num 属性不会重置。为什么会发生这种情况?
- python-3.x - FastAPI 通过 SqlAlchemy 处理多个数据库连接
- python - 从 url 响应(文本文件)解析 XML 错误,开始时带有 HTML 块
- c++ - 我正在尝试在 C++ 中使用运算符重载,但是当我去实现该函数时,它会提供此错误
- assembly - 如何在汇编中初始化数组的大小和指向数组的指针?
- regex - IDA 搜索多条指令
- python - 从python中的前导零中只打印一个零
- cmake - Cmake 的 SET 会发生什么
- amazon-web-services - 在 AWS Route 53 中创建子域并在 WIX 上配置以路由子域请求
- .htaccess - htaccess 重写规则,带有数字作为子域名的一部分