将UICollectionView滚动到节标题视图

时间:2022-09-06 20:47:42

The code below scrolls to the right cell in UICollectionView, but the section header view is hidden behind UINavigationBar in my case. I believe I should use scrollRectToVisible instead and my question is, what is the right way to calculate the CGRect (y position) when the numberOfRows in a given section is variable.

下面的代码在UICollectionView中滚动到右侧单元格,但在我的情况下,节标题视图隐藏在UINavigationBar后面。我相信我应该使用scrollRectToVisible而我的问题是,当给定部分中的numberOfRows是可变的时,计算CGRect(y位置)的正确方法是什么。

- (void)scrollToPricing:(NSUInteger)row {

    [self.collectionView scrollToItemAtIndexPath:
      [NSIndexPath indexPathForItem:0 
                          inSection:row] 
                   atScrollPosition:UICollectionViewScrollPositionTop 
                           animated:YES];
}

6 个解决方案

#1


10  

I think this may help you

我想这可能会对你有所帮助

UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];

Then you can access the location through attributes.frame

然后,您可以通过attributes.frame访问该位置

#2


11  

Seems like all the answers are overly complex. This works for me:

似乎所有答案都过于复杂。这对我有用:

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)

Swift 3:

斯威夫特3:

if let attributes = collectionView.collectionViewLayout.layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: IndexPath(item: 0, section: section)) {
    collectionView.setContentOffset(CGPoint(x: 0, y: attributes.frame.origin.y - collectionView.contentInset.top), animated: true)
}

#3


5  

First, get the frame for the header in the section:

首先,获取节中标题的框架:

- (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);
}

Note: I just put a value of 1 for the indexPath.item. You might need to change this to something appropriate for your implementation.

注意:我只为indexPath.item设置了值1。您可能需要将其更改为适合您的实现的内容。

Then, scroll the UIScrollView to the point at the top of the header:

然后,将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];
}

Note: you must subtract the contentInset, otherwise it will be discarded and your scrollview will scroll behind the status bar and/or navigation bar.

注意:您必须减去contentInset,否则它将被丢弃,您的scrollview将滚动状态栏和/或导航栏后面。

#4


0  

// [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];

#5


0  

// 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];

#6


0  

The easiest way is to use the section header frame.origin.x and frame.origin.y and then add up section header height with the item height to create a CGRect to scroll to.

最简单的方法是使用截面标题frame.origin.x和frame.origin.y,然后将截面标题高度与项目高度相加,以创建要滚动到的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);

#1


10  

I think this may help you

我想这可能会对你有所帮助

UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];

Then you can access the location through attributes.frame

然后,您可以通过attributes.frame访问该位置

#2


11  

Seems like all the answers are overly complex. This works for me:

似乎所有答案都过于复杂。这对我有用:

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)

Swift 3:

斯威夫特3:

if let attributes = collectionView.collectionViewLayout.layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: IndexPath(item: 0, section: section)) {
    collectionView.setContentOffset(CGPoint(x: 0, y: attributes.frame.origin.y - collectionView.contentInset.top), animated: true)
}

#3


5  

First, get the frame for the header in the section:

首先,获取节中标题的框架:

- (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);
}

Note: I just put a value of 1 for the indexPath.item. You might need to change this to something appropriate for your implementation.

注意:我只为indexPath.item设置了值1。您可能需要将其更改为适合您的实现的内容。

Then, scroll the UIScrollView to the point at the top of the header:

然后,将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];
}

Note: you must subtract the contentInset, otherwise it will be discarded and your scrollview will scroll behind the status bar and/or navigation bar.

注意:您必须减去contentInset,否则它将被丢弃,您的scrollview将滚动状态栏和/或导航栏后面。

#4


0  

// [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];

#5


0  

// 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];

#6


0  

The easiest way is to use the section header frame.origin.x and frame.origin.y and then add up section header height with the item height to create a CGRect to scroll to.

最简单的方法是使用截面标题frame.origin.x和frame.origin.y,然后将截面标题高度与项目高度相加,以创建要滚动到的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);