我有一个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)
}
}
答案 0 :(得分:1)
好像mousemove,% A_CaretX, A_CaretY
具有UIScrollView
属性,默认情况下将其设置为bounces
。
从文档中:
如果此属性的值为true,则滚动视图在其滚动时会反弹 遇到内容的边界。跳动在视觉上指示 滚动已到达内容的边缘。如果值为假, 滚动立即在内容边界停止,而不会反弹。 默认值为true。
这说明了颤抖的行为,即在应用动画的同时达到边界时被顶部约束校正的情况。
我在true
中设置了collectionView.bounces = false
,它的工作原理与现在一样。