UIScrollView snaps to position while scrolling

I am trying to implement a scroll view that snaps to points when scrolling .

All the messages that I saw about snapping to the after point, the user finished dragging and dropping the scroll. I want it to be attached while dragging.

So far I have this to stop the inertia after the drag and it works fine:

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { targetContentOffset.memory = scrollView.contentOffset } 

I tried this but did not work as desired:

  var scrollSnapHeight : CGFloat = myScrollView.contentSize.height/10 

scrollViewDidScroll:

 func scrollViewDidScroll(scrollView: UIScrollView) { let remainder : CGFloat = scrollView.contentOffset.y % scrollSnapHeight var scrollPoint : CGPoint = scrollView.contentOffset if remainder != 0 && scrollView.dragging { if self.lastOffset > scrollView.contentOffset.y //Scrolling Down { scrollPoint.y += (scrollSnapHeight - remainder) NSLog("scrollDown") } else //Scrolling Up { scrollPoint.y -= (scrollSnapHeight - remainder) } scrollView .setContentOffset(scrollPoint, animated: true) } self.lastOffset = scrollView.contentOffset.y; } 
+6
source share
2 answers

This approach will enable / disable the scrollEnabled property of UIScrollView .

When scrollView scrolls outside the specified scrollSnapHeight , make scrollEnabled to false . This will stop scrolling. Then run the scroll again for the next drag.

 extension ViewController: UIScrollViewDelegate { func scrollViewDidScroll(scrollView: UIScrollView) { if scrollView.contentOffset.y > lastOffset + scrollSnapHeight { scrollView.scrollEnabled = false } else if scrollView.contentOffset.y < lastOffset - scrollSnapHeight { scrollView.scrollEnabled = false } } func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { guard !decelerate else { return } setContentOffset(scrollView) } func scrollViewWillBeginDecelerating(scrollView: UIScrollView) { setContentOffset(scrollView) } } 

 func setContentOffset(scrollView: UIScrollView) { let stopOver = scrollSnapHeight var y = round(scrollView.contentOffset.y / stopOver) * stopOver y = max(0, min(y, scrollView.contentSize.height - scrollView.frame.height)) lastOffset = y scrollView.setContentOffset(CGPointMake(scrollView.contentOffset.x, y), animated: true) scrollView.scrollEnabled = true } 
+5
source

Subclass UIScrollView / UICollectionView

This solution does not require you to raise your finger to disconnect and work while scrolling. If you need it for vertical scrolling, and not for horizontal scrolling, just replace x with y.

Set snapPoint to the content offset where you want the snap center to be.

Set snapOffset to a radius around the point where snap is required.

If you need to know if scrollView was bound, just check the isSnapped variable.

 class UIScrollViewSnapping : UIScrollView { public var snapPoint: CGPoint? public var snapOffset: CGFloat? public var isSnapped = false public override var contentOffset: CGPoint { set { if let snapPoint = self.snapPoint, let snapOffset = self.snapOffset, newValue.x > snapPoint.x - snapOffset, newValue.x < snapPoint.x + snapOffset { self.isSnapped = true super.contentOffset = snapPoint } else { self.isSnapped = false super.contentOffset = newValue } } get { return super.contentOffset } } } 
+1
source

All Articles