Ich verwende UICollectionView
zum ersten Mal in meiner iPad-Anwendung . Ich habe UICollectionView
so eingestellt, dass Größe und Zellengröße gleich sind, dh nur eine Zelle wird gleichzeitig angezeigt.
Problem: Wenn der Benutzer jetzt UICollectionView scrollt, muss ich wissen, welche Zelle sichtbar ist. Ich muss andere Benutzeroberflächenelemente bei Änderung aktualisieren. Ich habe keine Delegatmethode dafür gefunden. Wie kann ich das erreichen?
Code:
[self.mainImageCollection setTag:MAIN_IMAGE_COLLECTION_VIEW];
[self.mainImageCollection registerClass:[InspirationMainImageCollectionCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.mainImageFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.mainImageFlowLayout setMinimumInteritemSpacing:0.0f];
[self.mainImageFlowLayout setMinimumLineSpacing:0.0f];
self.mainImageFlowLayout.minimumLineSpacing = 0;
[self.mainImageCollection setPagingEnabled:YES];
[self.mainImageCollection setShowsHorizontalScrollIndicator:NO];
[self.mainImageCollection setCollectionViewLayout:self.mainImageFlowLayout];
Was ich versucht habe:
Da UICollectionView
mit UIScrollView
übereinstimmt, bekam ich, wenn der Benutzer-Scroll mit der UIScrollViewDelegate
-Methode endet
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
Aber innerhalb der oben genannten Funktion, wie kann ich den aktuellen sichtbaren Zellenindex von UICollectionView
bekommen ???
Die Methode [collectionView visibleCells] liefert Ihnen alle Array von visibleCells, die Sie möchten. Verwenden Sie es, wenn Sie möchten
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
NSLog(@"%@",indexPath);
}
}
indexPathsForVisibleItems
kann in den meisten Situationen funktionieren, aber manchmal gibt es ein Array mit mehr als einem Indexpfad zurück. In solchen Situationen können Sie so etwas tun:
CGRect visibleRect = (CGRect){.Origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
Dies funktioniert besonders gut, wenn jedes Element in Ihrer Sammlungsansicht den gesamten Bildschirm einnimmt.
Swift-Version
let visibleRect = CGRect(Origin: collectionView.contentOffset, size: collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint)
Arbeitsantworten in Swift 2.2 kombiniert:
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = self.collectionView.contentOffset
visibleRect.size = self.collectionView.bounds.size
let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))
let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)
guard let indexPath = visibleIndexPath else { return }
print(indexPath)
}
Swift 3 & Swift 4 :
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = collectionView.contentOffset
visibleRect.size = collectionView.bounds.size
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return }
print(indexPath)
}
Der Vollständigkeit halber ist dies die Methode, die für mich gelaufen ist. Es war eine Kombination der Methoden von @Anthony & @ iAn.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
CGRect visibleRect = (CGRect){.Origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
NSLog(@"%@",visibleIndexPath);
}
UICollectionViewDelegate-Methoden werden wahrscheinlich am besten verwendet: (Swift 3)
// Called before the cell is displayed
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print(indexPath.row)
}
// Called when the cell is displayed
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print(indexPath.row)
}
Ich möchte nur für andere hinzufügen: Aus irgendeinem Grund habe ich nicht die Zelle erhalten, die für den Benutzer sichtbar war, als ich zu previous cell in collectionView mit pagingEnabled blätterte.
Also füge ich den Code in dispatch_async ein, um ein wenig "air" Zu geben, und das funktioniert für mich.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
dispatch_async(dispatch_get_main_queue(), ^{
UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];
[visibleCell doSomthing];
});
}
Für Swift 3.0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(Origin: colView.contentOffset, size: colView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let indexPath = colView.indexPathForItem(at: visiblePoint)
}
Swift 3.0
Einfachste Lösung, mit der Sie indexPath für sichtbare Zellen erhalten.
yourCollectionView.indexPathsForVisibleItems
gibt das Array von Indexpfad zurück.
Nehmen Sie einfach das erste Objekt aus dem Array wie folgt.
yourCollectionView.indexPathsForVisibleItems.first
Ich denke, es sollte auch mit Objective-C gut funktionieren.
var visibleCurrentCellIndexPath: IndexPath? {
for cell in self.collectionView.visibleCells {
let indexPath = self.collectionView.indexPath(for: cell)
return indexPath
}
return nil
}
Sie können scrollViewDidEndDecelerating
: dafür verwenden
//@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.collectionView visibleCells]) {
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
NSUInteger lastIndex = [indexPath indexAtPosition:[indexPath length] - 1];
NSLog(@"visible cell value %d",lastIndex);
}
}
@ Anthony's Antwort in Swift 3.0 umwandeln hat für mich perfekt funktioniert:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = yourCollectionView.contentOffset
visibleRect.size = yourCollectionView.bounds.size
let visiblePoint = CGPoint(x: CGFloat(visibleRect.midX), y: CGFloat(visibleRect.midY))
let visibleIndexPath: IndexPath? = yourCollectionView.indexPathForItem(at: visiblePoint)
print("Visible cell's index is : \(visibleIndexPath?.row)!")
}
Überprüfen Sie auch dieses Snippet
let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)
Das ist eine alte Frage, aber in meinem Fall ...
- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {
_m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.firstObject].row;
}
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
_m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.lastObject].row;
}