web-dev-qa-db-fra.com

Comment faire défiler UICollectionViewCell par programme dans IOS?

J'ai une UICollectionView verticale avec chaque cellule reprenant l'intégralité du self.view.frame. Je peux facilement glisser vers le haut pour passer d'une cellule à l'autre, mais j'aimerais faire la même chose en appuyant sur un bouton.

J'ai essayé d'utiliser:

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated

Et:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated

Ils fonctionnent, mais ils «masquent» temporairement la currentCell pour présenter la nextCell, tandis que le balayage affiche les deux cellules pendant la transition.

Idéalement, j'aimerais utiliser:

- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated

Mais je ne sais pas comment accéder à la variable indexPath... de nextCell. J'ai essayé:

NSIndexPath *nextIndexPath = [_collectionView indexPathForItemAtPoint:CGPointMake(25, (_collectionView.frame.size.height-25)*(_currentIndexRowForCellOnScreen+1))];

_currentIndexRowForCellOnScreen est le indexPath.row de la première apparition de la UICollectionView à:

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

Mais quand je le mets dans:

- (NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell

il retourne NULL après la première cellule et n'anime pas ....

Toute direction serait grandement appréciée. Merci pour votre temps.

11
Rhotick

En supposant que votre collectionView ne contient qu'une section et que chaque élément occupe l'intégralité du cadre, vous pouvez procéder de la sorte.

  NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems];
  NSIndexPath *currentItem = [visibleItems objectAtIndex:0];
  NSIndexPath *nextItem = [NSIndexPath indexPathForItem:currentItem.item + 1 inSection:currentItem.section];
  [self.collectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
40
MDB983

Voici les versions de Swift

Swift 2.x:

let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems()
let currentItem: NSIndexPath = visibleItems.objectAtIndex(0) as! NSIndexPath
let nextItem: NSIndexPath = NSIndexPath(forRow: currentItem.item + 1, inSection: 0)
self.collectionView.scrollToItemAtIndexPath(nextItem, atScrollPosition: .Top, animated: true)

Swift 3.x

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)
self.collectionView.scrollToItem(at: nextItem, at: .top, animated: true)
6

De loin c'est la meilleure approche que j'ai rencontrée, l'astuce consiste à faire défiler jusqu'au cadre qui contient les objets suivants. S'il vous plaît se référer le code

@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)
}
6
Mr. Bean

Swift 4.1 réponse 

    let visibleItems = self.collectionView.indexPathsForVisibleItems
    let currentItem = visibleItems.first
    let nextRow = (currentItem?.row)! + visibleItems.count
    if nextRow < elementArray.count {
        let nextIndexPath = IndexPath.init(row: nextRow, section: (currentItem?.section)!)
        self.collectionView.scrollToItem(at: nextIndexPath, at: UICollectionViewScrollPosition.left, animated: true)
    } else {
        let nextIndexPath = IndexPath.init(row: 0, section: (currentItem?.section)!)
        self.collectionView.scrollToItem(at: nextIndexPath, at: UICollectionViewScrollPosition.right, animated: true)
    }

Modifiez la position de défilement en fonction de vos besoins et du nombre de lignes que vous souhaitez ignorer (ici, j'ai sauté visibleItems.count).

1
Akila Wasala