Reputation: 1204
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
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
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
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
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
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
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:
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
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