Lenny1357
Lenny1357

Reputation: 778

How to programmatically scroll through a collection view?

I have a collection view in my view. In the cells are image views and it has one section.

I now want to scroll programmatically through the images. I want the animation to happen endless so it starts with item one after reaching item 10.

It also would be helpful if you provide some method where to put animations like the cells getting bigger after getting programmatically swiped in from right.

Upvotes: 27

Views: 31600

Answers (4)

Đorđe Nilović
Đorđe Nilović

Reputation: 3739

Swift 5

Based on Mr.Bean's answer, here is an elegant way using UICollectionView extension:

extension UICollectionView {
    func scrollToNextItem() {
        let contentOffset = CGFloat(floor(self.contentOffset.x + self.bounds.size.width))
        self.moveToFrame(contentOffset: contentOffset)
    }

    func scrollToPreviousItem() {
        let contentOffset = CGFloat(floor(self.contentOffset.x - self.bounds.size.width))
        self.moveToFrame(contentOffset: contentOffset)
    }

    func moveToFrame(contentOffset : CGFloat) {
        self.setContentOffset(CGPoint(x: contentOffset, y: self.contentOffset.y), animated: true)
    }
}

Now you can use it wherever you want:

collectionView.scrollToNextItem()
collectionView.scrollToPreviousItem()

Upvotes: 37

Sreeraj VR
Sreeraj VR

Reputation: 1574

You can use this UICollectionView extension (Swift 4.2)

        extension UICollectionView {

        func scrollToNextItem() {
            let scrollOffset = CGFloat(floor(self.contentOffset.x + self.bounds.size.width))
            self.scrollToFrame(scrollOffset: scrollOffset)
        }

        func scrollToPreviousItem() {
            let scrollOffset = CGFloat(floor(self.contentOffset.x - self.bounds.size.width))
            self.scrollToFrame(scrollOffset: scrollOffset)
        }

        func scrollToFrame(scrollOffset : CGFloat) {
            guard scrollOffset <= self.contentSize.width - self.bounds.size.width else { return }
            guard scrollOffset >= 0 else { return }
            self.setContentOffset(CGPoint(x: scrollOffset, y: self.contentOffset.y), animated: true)
        }
    }

And the usage will be like

yourCollectionView.scrollToNextItem()
yourCollectionView.scrollToPreviousItem()

Upvotes: 4

Jelly
Jelly

Reputation: 4522

There are two methods that could help you achieve this:

func scrollToItemAtIndexPath(indexPath: NSIndexPath,
        atScrollPosition scrollPosition: UICollectionViewScrollPosition,
                animated animated: Bool)

or

func setContentOffset(contentOffset: CGPoint,
         animated animated: Bool)

Both are on UICollectionView so you can use whatever seems more convenient. To create a custom animation for this however is more difficult. A quick solution depending on what you need could be this answer.

Swift 4, iOS 11:

// UICollectionView method
func scrollToItem(at indexPath: IndexPath, 
                  at scrollPosition: UICollectionViewScrollPosition,  
                  animated: Bool)

// UIScrollView method
func setContentOffset(_ contentOffset: CGPoint, animated: Bool)

Upvotes: 36

Mr. Bean
Mr. Bean

Reputation: 4281

By far this is the best approach i have encountered, the trick is to scroll to the frame which is containing next objects. Please refer the code

/* -------------- display previous friends action ----------------*/
@IBAction func actionPreviousFriends(_ sender: Any) {

    let collectionBounds = self.collectionView.bounds
    let contentOffset = CGFloat(floor(self.collectionView.contentOffset.x - collectionBounds.size.width))
    self.moveToFrame(contentOffset: contentOffset)
}

/* -------------- display next friends action ----------------*/
@IBAction func actionNextFriends(_ sender: Any) {

    let collectionBounds = self.collectionView.bounds
    let contentOffset = CGFloat(floor(self.collectionView.contentOffset.x + collectionBounds.size.width))
    self.moveToFrame(contentOffset: contentOffset)
}

func moveToFrame(contentOffset : CGFloat) {

    let frame: CGRect = CGRect(x : contentOffset ,y : self.collectionView.contentOffset.y ,width : self.collectionView.frame.width,height : self.collectionView.frame.height)
    self.collectionView.scrollRectToVisible(frame, animated: true)
}

Upvotes: 15

Related Questions