Skip to content

Instantly share code, notes, and snippets.

@WonderJeffy
Last active December 30, 2024 09:47
Show Gist options
  • Save WonderJeffy/5978bcbf91cf8984c1bd3aff88558712 to your computer and use it in GitHub Desktop.
Save WonderJeffy/5978bcbf91cf8984c1bd3aff88558712 to your computer and use it in GitHub Desktop.
var currentSection = 0
extension MoviesSubViewController: UIScrollViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard collectionView == scrollView as? UICollectionView else { return }
let touches = scrollView.panGestureRecognizer.numberOfTouches
guard scrollView.isDecelerating && touches == 0 else { return }
guard collectionView.numberOfSections > currentSection else { return }
let cellCount = collectionView.numberOfItems(inSection: currentSection)
let minY = collectionView.cellForItem(at: IndexPath(row: 0, section: currentSection))?.frame.minY ?? -300
let maxY = collectionView.cellForItem(
at: IndexPath(row: cellCount - 1, section: currentSection)
)?.frame.maxY ?? (minY + view.height)
if scrollView.contentOffset.y < minY {
scrollView.contentOffset.y = minY
}
let maxOffset = maxY - view.height
if maxOffset > minY, scrollView.contentOffset.y > maxOffset {
scrollView.contentOffset.y = maxOffset
}
}
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
guard !decelerate else { return }
scrollToNearestSection(scrollView)
}
public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
let velocity = scrollView.panGestureRecognizer.velocity(in: self.view)
if velocity.y > 100 {
scrollToPreviousSection(scrollView)
}
else if velocity.y < -100 {
scrollToNextSection(scrollView)
}
else {
scrollToNearestSection(scrollView)
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
}
private func scrollToNextSection(_ scrollView: UIScrollView) {
scrollToNearestSection(scrollView, offset: 1)
}
private func scrollToPreviousSection(_ scrollView: UIScrollView) {
scrollToNearestSection(scrollView, offset: -1)
}
private func scrollToNearestSection(_ scrollView: UIScrollView, offset: Int = 0) {
let visibleSections = Set(collectionView.indexPathsForVisibleItems.map { $0.section })
guard visibleSections.count > 1 else { return }
guard collectionView == scrollView as? UICollectionView else { return }
// 以屏幕中间的位置为准,找到最近的cell 对应的 section
let point = CGPoint(x: 100, y: view.height * 0.5)
let centerPoint = collectionView.convert(point, from: view)
guard let indexPath = collectionView.indexPathForItem(at: centerPoint) else { return }
guard indexPath.section + offset < collectionView.numberOfSections else {
return
}
var targetSection = indexPath.section
if (offset != 0) {
targetSection = max(currentSection + offset, 0)
}
let tragetIndexPath = IndexPath(row: 0, section: targetSection)
currentSection = tragetIndexPath.section
collectionView.scrollToItem(at: tragetIndexPath, at: .top, animated: true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment