ios UICollectionView 和自定义 UICollectionReusableView 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16579740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:36:08  来源:igfitidea点击:

UICollectionView & custom UICollectionReusableView not works

iosxibuicollectionviewuicollectionreusableview

提问by Romowski

I'm trying to use custom UICollectionReusableView(which has own class and XIB) in my UICollectionViewheader. But after fetching data in the place of header I have nothing.

我试图UICollectionReusableView在我的UICollectionView标题中使用自定义(它有自己的类和 XIB)。但是在标题的位置获取数据后,我什么都没有。

My steps:

我的步骤:

  1. Registering class in viewDidLoad:

     [self.collectionView registerClass:[CollectionViewHeader class] 
      forSupplementaryViewOfKind: UICollectionElementKindSectionHeader 
      withReuseIdentifier:@"HeaderView"];
    
  2. Trying to show:

    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
    UICollectionReusableView *reusableView = nil;
    
    if (kind == UICollectionElementKindSectionHeader) {
        CollectionViewHeader *collectionHeader = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
    
        NSInteger section = [indexPath section];
        id <NSFetchedResultsSectionInfo> sectionInfo = [fetchRecipes sections][section];
        collectionHeader.headerLabel.text = @"bla-bla-bla";
    
        reusableView = collectionHeader;
    }
    
    return reusableView;
    }
    
  1. viewDidLoad 中注册类:

     [self.collectionView registerClass:[CollectionViewHeader class] 
      forSupplementaryViewOfKind: UICollectionElementKindSectionHeader 
      withReuseIdentifier:@"HeaderView"];
    
  2. 试图显示:

    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
    UICollectionReusableView *reusableView = nil;
    
    if (kind == UICollectionElementKindSectionHeader) {
        CollectionViewHeader *collectionHeader = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
    
        NSInteger section = [indexPath section];
        id <NSFetchedResultsSectionInfo> sectionInfo = [fetchRecipes sections][section];
        collectionHeader.headerLabel.text = @"bla-bla-bla";
    
        reusableView = collectionHeader;
    }
    
    return reusableView;
    }
    

Can anybody tell me what's wrong? ) Thanks for any advice

谁能告诉我出了什么问题?) 感谢您的任何建议

回答by Anil Varghese

I think you are adding label to the xib. So you need to registerNib:for the header view instead of registerClass:

我认为您正在向 xib 添加标签。所以你需要registerNib:对于标题视图而不是registerClass:

回答by andrewoodleyjr

  1. Register Your header nib/xib in the viewDidLoad section.

    [self.collectionView registerNib:  [UINib nibWithNibName:@"headerCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"headerCell"]; 
    
  2. Create the custom supplementary view cell.

    - (headerCollectionViewCell *)collectionView:(UICollectionView *)collectionViews viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionReusableView *reusableView = nil;
    
        if (kind == UICollectionElementKindSectionHeader) {
    
            UINib *nib = [UINib nibWithNibName:@"headerCollectionViewCell" bundle:nil];
    
            [collectionViews registerNib:nib forCellWithReuseIdentifier:@"headerCell"];
    
            headerCollectionViewCell *collectionHeader = [collectionViews dequeueReusableCellWithReuseIdentifier:@"headerCell" forIndexPath:indexPath];
            collectionHeader.titleLabel.text = @"What";
    
            reusableView = collectionHeader;
       }
    
       return reusableView;
    }
    
  1. 在 viewDidLoad 部分注册您的头 nib/xib。

    [self.collectionView registerNib:  [UINib nibWithNibName:@"headerCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"headerCell"]; 
    
  2. 创建自定义补充视图单元格。

    - (headerCollectionViewCell *)collectionView:(UICollectionView *)collectionViews viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionReusableView *reusableView = nil;
    
        if (kind == UICollectionElementKindSectionHeader) {
    
            UINib *nib = [UINib nibWithNibName:@"headerCollectionViewCell" bundle:nil];
    
            [collectionViews registerNib:nib forCellWithReuseIdentifier:@"headerCell"];
    
            headerCollectionViewCell *collectionHeader = [collectionViews dequeueReusableCellWithReuseIdentifier:@"headerCell" forIndexPath:indexPath];
            collectionHeader.titleLabel.text = @"What";
    
            reusableView = collectionHeader;
       }
    
       return reusableView;
    }
    

回答by Zanael

class CustomFlowLayout: UICollectionViewFlowLayout {

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
        var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()

        for attributes in attributesForElementsInRect! {

            if !(attributes.representedElementKind == UICollectionElementKindSectionHeader
                || attributes.representedElementKind == UICollectionElementKindSectionFooter) {

                // cells will be customise here, but Header and Footer will have layout without changes.
            }

            newAttributesForElementsInRect.append(attributes)
        }

        return newAttributesForElementsInRect
    }
}


class YourViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let headerNib = UINib.init(nibName: "HeaderCell", bundle: nil)
        collectionView.register(headerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")

        let footerNib = UINib.init(nibName: "FooterCell", bundle: nil)
        collectionView.register(footerNib, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "FooterCell")
    }


    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        switch kind {
        case UICollectionElementKindSectionHeader:
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
            return headerView
        case UICollectionElementKindSectionFooter:
            let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterCell", for: indexPath) as! FooterCell
            return footerView
        default:
            return UICollectionReusableView()
        }
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 45)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 25)
    }
}

回答by timurbeg

Just in case if someone needs solution. You don't have to register the header class using

以防万一有人需要解决方案。您不必使用注册头类

[self.collectionView registerClass:...]

Just use the layout's delegate method to return the header class.

只需使用布局的委托方法返回头类。

回答by gbk

Actually there is can be few reasons:

其实可能有以下几个原因:

  1. (most common) If u add u'r suplementaryViewin storyboard, and then try to register class

    [self.stickyCollectionView registerClass:[<CLASSFORSUPPLEMENTARYVIEWW> class]
              forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                     withReuseIdentifier:NSStringFromClass([<CLASSFORSUPPLEMENTARYVIEWW> class])];
    
  1. (最常见)如果你suplementaryView在故事板中添加你,然后尝试注册类

    [self.stickyCollectionView registerClass:[<CLASSFORSUPPLEMENTARYVIEWW> class]
              forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                     withReuseIdentifier:NSStringFromClass([<CLASSFORSUPPLEMENTARYVIEWW> class])];
    

u will get suplementaryView, but not that u create (standard one) - u will see obj, but actually this is will be like placeholder.

你会得到suplementaryView,但不是你创造的(标准的) - 你会看到 obj,但实际上这就像占位符。

Example:

例子:

enter image description here

在此处输入图片说明

Here u can see that obj was created, but outlets are nil (in this simple case only one outlet - _monthNameLabel).

在这里您可以看到 obj 已创建,但出口为零(在这种简单的情况下只有一个出口 - _monthNameLabel)。

  1. I see few times this problem also
  1. 我也看到几次这个问题

If u create separate Objfor handling dataSourse/delegate for collectionViewand add reference outlet to it, and in initmethods try to register class to u'r outlet (assumed that view created in separate nib file), u will also receive same result like previous, but reason another - u'r outlet is nil here:

如果您创建单独的Obj用于处理数据源/委托collectionView并为其添加引用插座,并且在init方法中尝试将类注册到您的插座(假设在单独的 nib 文件中创建的视图),您也将收到与以前相同的结果,但是另一个原因 - 你的出口在这里为零:

enter image description here

在此处输入图片说明

As solution u for example can use custom setter for this like:

例如,作为解决方案,您可以使用自定义设置器,例如:

#pragma mark - CustomAccessors

- (void)setcCollectionView:(UICollectionView *)collectionView
{
    _collectionView = collectionView;

    [self.stickyCollectionView registerNib:...];
}
  1. as suggested by @Anil Varghese
  1. 正如@Anil Varghese 所建议的

u can use registerClassinstead of registerNib

你可以用registerClass代替registerNib

回答by Hyman

Xcode 9, Swift 4:

Xcode 9,斯威夫特 4:

Register UICollectionReusableViewin viewDidLoad

注册UICollectionReusableViewviewDidLoad

self.collectionView.register(UINib(nibName: "DashBoardCollectionReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "ReuseIdentifier")

回答by 93sauu

You was registering correctly the class and the delegate is implemented correctly.

您正确注册了课程并且正确实现了委托。

The problem can be that the flow layout (by default) is not configured for header view, do you have this line in the code or interface file?

问题可能是流布局(默认情况下)没有为标题视图配置,你的代码或界面文件中有这行吗?

UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)_collectionView.collectionViewLayout;
flowLayout.headerReferenceSize = CGSizeMake(CGRectGetWidth(_collectionView.bounds), 100);