UICollectionView 具有自调整大小的单元格未正确计算 contentSize

Posted

技术标签:

【中文标题】UICollectionView 具有自调整大小的单元格未正确计算 contentSize【英文标题】:UICollectionView with selfsizing cells not calculating contentSize properly 【发布时间】:2014-10-10 08:07:34 【问题描述】:

如 WWDC 2014 所示,我有 UICollection 视图使用自定尺寸单元格。

我想把它放在 UITableViewCell 中并显示一组标签(我想要实现的目标的良好参考是在 Foursquare 应用程序中:)

我的问题是,使用自行调整大小的单元格时,内容大小返回不正确。 我准备了一些快速演示来展示问题:

- (void)viewDidLoad

    [super viewDidLoad];

    self.elements = [NSMutableArray array];
    for (int i = 0; i < 23; i++)
    
        [self.elements addObject:[self randomString]];
    

    UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc] init];
    layout.estimatedItemSize = CGSizeMake(50, 30);

    self.collectionView=[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
    [self.collectionView setDataSource:self];
    [self.collectionView setDelegate:self];

    UINib *cellNib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
    [self.collectionView registerNib:cellNib forCellWithReuseIdentifier:@"CustomCell"];
    [self.collectionView setBackgroundColor:[UIColor blueColor]];
    [self.view addSubview:self.collectionView];


- (void) viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];

    self.collectionView.frame = CGRectMake(0, 0, self.collectionView.frame.size.width, self.collectionView.contentSize.height);


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    return [self.elements count];


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    CustomCell* cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath];
    cell.customLabel.text = [self.elements objectAtIndex:[indexPath row]];
    return cell;

当我用旧方法删除estimatedItemSize 并改用itemSize 或委托方法来计算大小时 - 它工作正常,所以我认为它使用estimatedItem 大小来获取内容大小。

有什么方法可以让它与自调整大小的单元格一起工作,并根据它的内容自动调整 UICollectionView 的大小?

【问题讨论】:

err... 我知道这没有帮助,但我建议现在不要在集合视图中使用自调整单元格。似乎 Apple 在实现这些 devforums.apple.com/… 方面做得不太好。 那么按照我的意愿实现它的方法是什么? :) 即使使用手动计算,我也无法预测 UICollectionView 需要多少空间来显示其内容 - 我需要预测 UITableViewCell 高度 :) 【参考方案1】:

我最终自己计算了尺寸:

- (CGSize) sizeForCellAtIndexPath:(NSIndexPath*) indexPath isMoreButton:(BOOL) isMoreButton

    TagCell* cell = (TagCell*) [[LayoutHelper sharedLayoutHelper] collectionCellFromNib:@"TagCell"];
    cell.tagLabel.text = [self.contactHashTags objectAtIndex:indexPath.row];
    CGSize size = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    CGSizeMake(size.width, cell.frame.size.height);


- (CGSize) sizeForCellAtIndexPath:(NSIndexPath*) indexPath isMoreButton:(BOOL) isMoreButton

    CGSize size = [self.dataSource sizeForCellAtIndexPath:indexPath isMoreButton:isMoreButton];

    //limit cell to view width
    size.width = MIN(size.width, self.frame.size.width);
    return size;

【讨论】:

FWIW,即使在 ios 10 中,我也遇到了与自调整单元格相同的问题。在下一个运行循环中,大小是正确的。手动调整大小是唯一的解决方案。 这真的很烦人。 iOS 11 修复了这个错误。【参考方案2】:

我的解决方法...动态添加插图。

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) 
    let isLastItem = indexPath.item == (collectionView.numberOfItems(inSection: indexPath.section) - 1)
    guard isLastItem else 
        return
    

    DispatchQueue.main.async 
        let inset = (cell.frame.maxX - collectionView.contentSize.width) + 10 // 10 is the right padding I want for my horizontal scroll
        collectionView.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: inset)
    

【讨论】:

以上是关于UICollectionView 具有自调整大小的单元格未正确计算 contentSize的主要内容,如果未能解决你的问题,请参考以下文章

具有异步图像加载的自调整 UICollectionView 单元格

UICollectionView 自调整大小的单元格

UICollectionView:使用动画和自定义布局调整单元格大小

如何将 UICollectionView 项目的大小调整为具有集合视图高度的正方形大小?

我在自定义 TableViewCell 中有一个 UICollectionView,但我无法自动调整 CollectionView 的大小

动态调整 UICollectionView 大小以确保没有项目间距