This article is published on my wechat official account. You can follow it by scanning the QR code at the bottom of the article or searching for HelloWorld Jieshao in wechat.

In my last post, I showed you how to use UICollectionView, a powerful control, to create a card rotation effect. Later, a user got in touch with me and said, “He had a problem. When he rolled the item width the same as the screen width, the scrolling effect was fine. But when the item width is set to a value smaller than the screen width, the scrolling bug will appear. How to solve this!

This problem does exist, because in the UICollectionView property, there is a pagination property called isPagingEnabled, which, when set to true, is equal to the width of the screen; When this pagination property is not set, its default value is false, so its scrolling does not have the pagination effect. The UICollectionView control can only page according to the size of the screen. The answer, of course, is no.

That custom scrolling page how to achieve! Still have to rely on our UICollectionViewFlowLayout; In the definition of UICollectionViewFlowLayout provides a rewritable function:

func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior
Copy the code

The value returned by this function determines the offset at which the UICollectionView stops scrolling. You can override this function for custom paging scrolling. The logic behind overriding this function is as follows:

  1. Define a coordinate point CGPoint to record the offset coordinates of the latest scroll
  2. Define two values: UICollectionView scrollable maximum offset and minimum offset is also 0
  3. The above function func targetContentOffset (…) is called each time the scroll stops In this function, there is a parameter proposedContentOffset that records the target displacement coordinates of the scroll, and the coordinates of the last scroll recorded can be used to determine whether to scroll left or right
  4. If the absolute value of the horizontal subtraction of the two coordinates is greater than some fixed value (such as 1/8 of the item width), paging can be determined, and the number of pages currently scrolling can be calculated using the proposedContentOffset displacement coordinates and the width of the item. If it is less than that fixed value, no paging occurs
  5. Finally, record the latest offset coordinates and return the offset when the UICollectionView stopped scrolling

Talk is cheap, show me the code,

class RowStyleLayout: UICollectionViewFlowLayout { private var lastOffset: CGPoint! override init() { super.init() lastOffset = CGPoint.zero } required init? (coder: NSCoder) {fatalError("init(coder:) has not been implemented")} // init func prepare() {super.prepare() self.collectionView? .activity Rate =.fast} // The return value of this activity, Override FUNc targetContentOffset(forProposedContentOffset proposedContentOffset) CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {// page width let pageSpace = self.stepspace () let offsetMax: CGFloat = self.collectionView! .contentSize.width - (pageSpace + self.sectionInset.right + self.minimumLineSpacing) let offsetMin: CGFloat = 0 // Modify the previous record position, X < offsetMin {lastOffset. X = offsetMin} else if lastOffset. X > OffsetMax {lastOffset. X = offsetMax} let offsetForCurrentPointX: CGFloat = abs(proposedcontentoffset.x-lastoffset.x) let velocityX = velocity.x False true, left to right let direction: Bool proposedContentOffset. X-ray lastOffset. (x) = 0 > var newProposedContentOffset: CGPoint = CGPoint. Zero if (offsetForCurrentPointX > pageSpace/8.0) && (lastOffset. X >= offsetMin) && (lastOffset Var pageFactor: NSInteger = 0 if velocityX! = 0 {// the faster the slide, PageFactor = abs(NSInteger(velocityX))} else {// Drag pageFactor = abs(NSInteger(offsetForCurrentPointX / PageFactor = pageFactor < 1? PageFactor = pageFactor < 1? PageFactor = pageFactor < 1? PageFactor = pageFactor < 1? PageFactor = pageFactor < 1? 1: (pageFactor < 3 ? 1: 2) let pageOffsetX: CGFloat = pageSpace * CGFloat(pageFactor) newProposedContentOffset = CGPoint(x: lastOffset.x + (direction ? pageOffsetX : -pageOffsetX), y: NewProposedContentOffset = CGPoint(x: lastoffset.x, y:);} else {newProposedContentOffset = CGPoint(x: lastOffset. LastOffset. Y)} lastOffset. X = newProposedContentOffset. X return newProposedContentOffset} / / every page of the spacing sliding public func stepSpace() -> CGFloat { return self.itemSize.width + self.minimumLineSpacing } }Copy the code

The running effect is as follows:

This is the end of this article, according to the international convention, the end of the article listed demo project address, like don’t forget to give and share.

Github.com/ShenJieSuzh…

Related reading:

Use UICollectionView to achieve the card rotation effect of home page

Follow my technical public account “HelloWorld Jieshao “to get more quality technical articles.