user934902
user934902

Reputation: 1204

Move collectionView on button click (Swift)

I have a CollectionView that I am using to display my onboarding screen. Each cell takes the full width and height of the view and currently I have it working fine swiping between each cell (page).

I have to implement a next button. This button will just move the collectionView over 1 index on each click (till the end). I am just trying to make it move right now and even though there a few similar questions I have not been able to come up with a solution this far.

This is what I have tried:

@IBAction func nextPageButtonClicked(_ sender: AnyObject) {
    let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
    let currentItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
    let nextItem: NSIndexPath = NSIndexPath(row: currentItem + 1, section: 0)
    self.collectionView.scrollToItem(at: nextItem as IndexPath, at: .left, animated: true)
}

I get an error about performing the binary operator on line 4 (currentItem + 1) but even if I hard code the number and try and run it, I still dont get the scroll to function

Upvotes: 6

Views: 17057

Answers (7)

Jitendra Patel
Jitendra Patel

Reputation: 1

Here is solution for scroll collection view on button click.

Note: sender.tag is used to handle left and right scrolling.

let visibleItems = collecitonView.indexPathsForVisibleItems.sorted { $0 < $1 }

guard let indexPath = sender.tag == 0 ? visibleItems.first : visibleItems.last else {
            return
        }
        
let nextItem: IndexPath = IndexPath(item: sender.tag == 0  ? indexPath.item - 1 : indexPath.item + 1, section: 0)
        
if nextItem.row < 10 && nextItem.row >= 0{
            
            collecitonView.scrollToItem(at: nextItem, at: .centeredHorizontally, animated: true)
        }

Upvotes: 0

utkarsh upadhyay
utkarsh upadhyay

Reputation: 31

For me using in ios 14, above solution didn't work properly. So here is the solution.

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)
}}

Usage:

func rightButtonTapped() {
    infoCollectionView.scrollToNextItem()
}

func leftButtonTapped() {
    infoCollectionView.scrollToPreviousItem()
}

Upvotes: 3

cevhers
cevhers

Reputation: 41

An issue with collectionView.scrollToItem function on ios 14. So You can try this

extension UICollectionView {
    func scrollToNextItem() {
        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)
        }
}

and this is your button action

@IBAction func nextButtonAct(_ sender: Any) {
   collectionView.scrollToNextItem()
}

Upvotes: 3

Abdelrahman Mohamed
Abdelrahman Mohamed

Reputation: 1046

for didTapBack you just need the current page but in didTapForward you need also to check currentPage if it does not arrive at last index of yourArray

if currentPage > self.yourArray.count - 2 {
    return
}

to be sure that you didn't arrive to the last index

@IBAction func didTapBack(_ sender: Any) {

    let indexPath = IndexPath(item: currentPage - 1, section: 0)
    collectionView.scrollToItem(at: indexPath, at: .left, animated: true)
}

@IBAction func didTapForward(_ sender: Any) {

    if currentPage > self.yourArray.count - 2 {
        return
    }

    let indexPath = IndexPath(item: currentPage + 1, section: 0)
    collectionView.scrollToItem(at: indexPath, at: .right, animated: true)
}

Upvotes: 0

Amit gupta
Amit gupta

Reputation: 553

Try these methods for left as well as right increment of your collection cell

For right increment

@IBAction func Btn_RightAction(_ sender: Any)
{
    let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
    let currentItem: IndexPath = visibleItems.object(at: 0) as! IndexPath
    let nextItem: IndexPath = IndexPath(item: currentItem.item + 1, section: 0)
           if nextItem.row < ImgArr.count {
        self.collectionView.scrollToItem(at: nextItem, at: .left, animated: true)

    }
}

For left increment

@IBAction func Btn_LeftAction(_ sender: Any)
{
    let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
    let currentItem: IndexPath = visibleItems.object(at: 0) as! IndexPath
    let nextItem: IndexPath = IndexPath(item: currentItem.item - 1, section: 0)
    if nextItem.row < ImgArr.count && nextItem.row >= 0{
        self.collectionView.scrollToItem(at: nextItem, at: .right, animated: true)

    }
}

Upvotes: 21

Shaky99
Shaky99

Reputation: 51

@IBAction func showNextItemCollectionViewOnClick(_ sender: Any) {

        let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray

        var minItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
        for itr in visibleItems {

            if minItem.row > (itr as AnyObject).row {
                minItem = itr as! NSIndexPath
            }
        }

        let nextItem = NSIndexPath(row: minItem.row + 1, section: 0)
        self.collectionView.scrollToItem(at: nextItem as IndexPath, at: .left, animated: true)
    }

Steps:

  1. Find all visible items in "visibleItems" variable
  2. Find min item present in the visible items
  3. Go to nextItem
  4. scroll to required item.

Note: this works even in case when more than one items are present in collection view & on button click we want "one" more item to be visible if we want movement of more than one item change "1" to required value.

Upvotes: 3

Callam
Callam

Reputation: 11539

You are trying to increment an indexPath, you must increment the indexPath's row.

let nextItem = NSIndexPath(row: currentItem.row + 1, section: 0)

Example

@IBAction func nextPageButtonClicked(_ sender: AnyObject) {

    guard let indexPath = collectionView.indexPathsForVisibleItems.first.flatMap({
        IndexPath(item: $0.row + 1, section: $0.section)
    }), collectionView.cellForItem(at: indexPath) != nil else {
        return
    }

    collectionView.scrollToItem(at: indexPath, at: .left, animated: true)
}

Upvotes: 13

Related Questions