我在iPad应用程序中第一次使用UICollectionView
。
我已将UICollectionView
设置为其大小和单元格大小相同,表示一次只显示一个单元格。
问题: 现在,当用户滚动UICollectionView时,我需要知道哪个单元格可见,我必须更新其他UI元素。我没有找到任何委托方法。我怎样才能做到这一点?
代码:
[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];
我尝试了什么:
当UICollectionView
符合UIScrollView
时,我用“UIScrollViewDelegate
方法结束用户滚动
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
但是在上面的函数中,如何获得UICollectionView
???
答案 0 :(得分:149)
indexPathsForVisibleItems
可能适用于大多数情况,但有时会返回一个包含多个索引路径的数组,并且找出你想要的那个可能很棘手。在这些情况下,你可以这样做:
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];
当集合视图中的每个项目占据整个屏幕时,此功能尤其有用。
Swift版本
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)
答案 1 :(得分:117)
方法[collectionView visibleCells]为您提供所需的所有visibleCells数组。当你想要
时使用它- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
NSLog(@"%@",indexPath);
}
}
答案 2 :(得分:67)
在Swift 2.2中结合使用的答案:
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)
}
答案 3 :(得分:18)
为了完整起见,这是最终为我工作的方法。这是@Anthony& amp; @ 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);
}
答案 4 :(得分:8)
只想为其他人添加: 出于某种原因,当我使用pagingEnabled滚动到collectionView中的上一个单元格时,我没有得到用户可见的单元格。
所以我在dispatch_async中插入代码给它一些" air" 这对我有用。
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
dispatch_async(dispatch_get_main_queue(), ^{
UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];
[visibleCell doSomthing];
});
}
答案 5 :(得分:8)
最好使用UICollectionViewDelegate方法:(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)
}
答案 6 :(得分:7)
对于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)
}
答案 7 :(得分:6)
Swift 3.0
最简单的解决方案,它将为您提供可见单元格的indexPath ..
yourCollectionView.indexPathsForVisibleItems
将返回indexpath数组。
从这个数组中取出第一个对象。
yourCollectionView.indexPathsForVisibleItems.first
我猜它也应该与Objective-C一起使用。
答案 8 :(得分:4)
var visibleCurrentCellIndexPath: IndexPath? {
for cell in self.collectionView.visibleCells {
let indexPath = self.collectionView.indexPath(for: cell)
return indexPath
}
return nil
}
答案 9 :(得分:2)
您可以使用scrollViewDidEndDecelerating
:为此
//@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);
}
}
答案 10 :(得分:1)
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)!")
}
答案 11 :(得分:0)
这是一个老问题但在我的情况下......
- (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;
}
答案 12 :(得分:0)
同时检查此代码段
let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)
答案 13 :(得分:0)
在此线程中,有很多解决方案都可以在单元格全屏显示的情况下发挥作用,但是它们使用了集合视图的边界和可见矩形的中点。但是,有一个简单的解决方案可以解决此问题
DispatchQueue.main.async {
let visibleCell = self.collImages.visibleCells.first
print(self.collImages.indexPath(for: visibleCell))
}
通过,您可以获得可见单元格的indexPath。我添加了DispatchQueue,因为当您快速滑动时,如果短暂显示下一个单元格,则没有dispactchQueue,您将获得简短显示的单元格的indexPath而不是屏幕上正在显示的单元格。
答案 14 :(得分:-1)
试试这个,它有效。 (在下面的示例中,我有3个单元格。)
{{1}}
答案 15 :(得分:-2)
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[1])
}
如果您想显示实际数字,则可以添加+1