下面的代码滚动到
UICollectionView
中的右侧单元格,但在我的例子中,节标题视图隐藏在 UINavigationBar
后面。我相信我应该使用 scrollRectToVisible
来代替,我的问题是,当给定 CGRect
中的 numberOfRows
是可变的时,计算 section
(y 位置)的正确方法是什么。
- (void)scrollToPricing:(NSUInteger)row {
[self.collectionView scrollToItemAtIndexPath:
[NSIndexPath indexPathForItem:0
inSection:row]
atScrollPosition:UICollectionViewScrollPositionTop
animated:YES];
}
似乎所有答案都过于复杂。这对我有用:
let attributes = self.collectionView.collectionViewLayout.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: NSIndexPath(forItem: 0, inSection: section))
self.collectionView.setContentOffset(CGPointMake(0, attributes!.frame.origin.y - self.collectionView.contentInset.top), animated: true)
斯威夫特5:
if let attributes = collectionView.collectionViewLayout.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: IndexPath(item: 0, section: section)) {
collectionView.setContentOffset(CGPoint(x: 0, y: attributes.frame.origin.y - collectionView.contentInset.top), animated: true)
}
我想这可能对你有帮助
UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];
然后您可以通过
attributes.frame
访问该位置
基于
@pixelfreak
答案
Swift 4.2
+ iOS 11 Safe Area
支持(适用于 iPhone X 及以上版本)if let attributes = collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionView.elementKindSectionHeader, at: IndexPath(item: 0, section: section)) {
var offsetY = attributes.frame.origin.y - collectionView.contentInset.top
if #available(iOS 11.0, *) {
offsetY -= collectionView.safeAreaInsets.top
}
collectionView.setContentOffset(CGPoint(x: 0, y: offsetY), animated: true) // or animated: false
}
快乐编码
首先,获取该部分中标题的框架:
- (CGRect)frameForHeaderForSection:(NSInteger)section {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:section];
UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];
CGRect frameForFirstCell = attributes.frame;
CGFloat headerHeight = [self collectionView:_collectionView layout:_layout referenceSizeForHeaderInSection:section].height;
return CGRectOffset(frameForFirstCell, 0, -headerHeight);
}
注意:我只是为
1
设置了 indexPath.item
值。您可能需要将其更改为适合您的实现的内容。
然后,将
UIScrollView
滚动到标题顶部的点:
- (void)scrollToTopOfSection:(NSInteger)section animated:(BOOL)animated {
CGRect headerRect = [self frameForHeaderForSection:section];
CGPoint topOfHeader = CGPointMake(0, headerRect.origin.y - _collectionView.contentInset.top);
[_collectionView setContentOffset:topOfHeader animated:animated];
}
注意:您必须减去
contentInset
,否则它将被丢弃,并且您的滚动视图将滚动到状态栏和/或导航栏后面。
// [myCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index_of_sec] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
Below code will fix your problem, as i have faced same issue and used this solution developed by me instead of above commented code.
UICollectionViewLayoutAttributes *attributes = [myCollectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index_of_sec]];
CGRect rect = attributes.frame;
[myCollectionView setContentOffset:CGPointMake(myCollectionView.frame.origin.x, rect.origin.y - HEIGHT_OF_YOUR_HEADER) animated:YES];
最简单的方法是使用 section header
frame.origin.x
和 frame.origin.y
,然后将 section header height
与 item height
添加到 CGRect
来滚动到。
let sectionHeaderAttributes: UICollectionViewLayoutAttributes = self.collectionView.layoutAttributesForItem(at: scrollToIndexPath)!;
let itemAttributes: UICollectionViewLayoutAttributes = self.collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionElementKindSectionHeader, at: scrollToIndexPath)!;
let combinedFrame: CGRect = CGRect(x: sectionHeaderAttributes.frame.origin.x, y: sectionHeaderAttributes.frame.origin.y, width: sectionHeaderAttributes.frame.width, height: sectionHeaderAttributes.frame.height + itemAttributes.frame.height);
collectionView.scrollRectToVisible(combinedFrame, animated: false);
// scroll to selected index
NSIndexPath* cellIndexPath = [NSIndexPath indexPathForItem:0 inSection:sectionIndex];
UICollectionViewLayoutAttributes* attr = [self.collectionView.collectionViewLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:cellIndexPath];
UIEdgeInsets insets = self.collectionView.scrollIndicatorInsets;
CGRect rect = attr.frame;
rect.size = self.collectionView.frame.size;
rect.size.height -= insets.top + insets.bottom;
CGFloat offset = (rect.origin.y + rect.size.height) - self.collectionView.contentSize.height;
if ( offset > 0.0 ) rect = CGRectOffset(rect, 0, -offset);
[self.collectionView scrollRectToVisible:rect animated:YES];
我发现接受的答案不再正常工作(2个标题粘在一起),特别是当集合视图必须向上滚动时(向下仍然可以正常工作)。
以下代码在任一方向上都可以完美运行:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
UICollectionViewLayoutAttributes *headerAttribs = [iconsCV layoutAttributesForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
UICollectionViewLayoutAttributes *attribs = [iconsCV layoutAttributesForItemAtIndexPath:indexPath];
CGPoint topOfHeader = CGPointMake(0, attribs.frame.origin.y -collectionV.contentInset.top -headerAttribs.bounds.size.height);
[collectionV setContentOffset:topOfHeader animated:YES];
最初面临类似的问题,直到我意识到
UICollectionView.ScrollPosition
可用于在集合视图框架中定位标题。
您只需使用 UICollectionViewScrollPositionCenteredVertically 选项即可使标题在集合视图框架的中心可见。
这是我在 Swift 4.2 中实现这一目标的方法:
let scrollableSection = IndexPath.init(row: 0, section: indexPath.item)
emojiCollectionView.scrollToItem(at: scrollableSection, at: .centeredVertically, animated: true)