【问题标题】:Update collection view height to fit all cells within a table view cell using Auto Layout使用自动布局更新集合视图高度以适应表格视图单元格中的所有单元格
【发布时间】:2015-06-18 07:05:22
【问题描述】:

我想利用 iOS 8 中新增的动态UITableViewCell 高度。我需要在UITableViewCell 中放置一个UICollectionView。我想确保集合视图中的所有单元格在屏幕上都是可见的,因此表格单元格的高度应该增加以适合集合视图。我几乎有这个工作。我只是无法将表格单元格设置为正确的大小 - 它的高度要么太长要么太短,并且在我与表格交互之前,一些布局问题是可见的(更多内容见下文)。

我已经为表格单元格的contentView 设置了集合视图的自动布局约束:前导、尾随、顶部和底部。然后我在集合视图上创建了一个高度约束,这样我就可以在计算出适合集合视图中所有单元格的适当高度后即时更新它的constant(因为我认为没有办法自动执行此操作)。

这是其余的设置。

viewDidLoad {
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 44
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    let cellDimension = self.collectionView.frame.size.width / 7 //always 7 columns

    let flowLayout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    flowLayout.itemSize = CGSizeMake(cellDimension, cellDimension)

    self.collectionViewHeightConstraint.constant = cellDimension * 4 //always 4 rows
}

我还没有实现heightForRowAtIndexPath

此设置会导致垂直约束冲突。我已经尝试降低约束的优先级并更改一堆组合中的关系,但没有一个导致所需的行为。如果我将高度约束的优先级降低到 999,表格视图单元格起初太高,但在我上下滚动表格视图后,表格单元格高度更新到预期高度。使用其他一些组合,根据优先级和我已应用于约束的关系。此外,在视图动画时,集合视图单元格未以正确的大小显示(但它们在动画完成时已正确调整),或者如果我重新加载表格,则集合视图单元格的大小不正确,直到我滚动桌子。

如何解决这些外观问题以获得动态表格视图单元格高度,其中包含一个完全可见的集合视图,该集合视图具有基于显示器宽度的动态单元格大小?

【问题讨论】:

  • 我建议将 rowHeight 设置“self.tableView.rowHeight =”从 ViewDidLoad 移动到 ViewWillAppear,您可能还想检查这个问题。 link
  • @KevinHorgan 这没有任何明显的区别。
  • 为了使自动布局在 UITableViewCell 中正常工作,您需要为 containerView 中的所有布局添加约束而不会丢失。否则自动布局将无法正常工作。查看以下链接,其中提供了自动布局设置的一些详细信息对于 tableviewcell stackoverflow.com/questions/29231390/…
  • @Ram 约束都已定义,从集合视图到 contentView 的顶部底部前导尾随。
  • AFAICS 的答案比这里提到的任何人都复杂。查看stackoverflow.com/questions/24126708/…

标签: ios uitableview swift autolayout uicollectionview


【解决方案1】:

这是我的处理方法,我认为这可以在 IB 中完成。

首先,我会设置 CV 单元格的最小大小,然后我会设置 CV 的拥抱优先级以尽可能紧密地拥抱其内容。这应该保证,除了所有外部影响之外,CV 将尝试具有使其所有单元格可见的尽可能小的尺寸。

接下来,我将使用 TBV 单元的内容视图和 CV 进行相同的游戏,也就是说,我将 TBV 单元的内容视图的拥抱优先级设置为尽可能紧密地拥抱 CV。再次强调,在忽略外部影响的情况下,TBV 单元应保持其需要保持的最小尺寸,以便完整显示 CV。

【讨论】:

    【解决方案2】:

    看看 forkingdog 如何解决相同的 tableview 单元格动态高度问题 > https://github.com/forkingdog/UITableView-FDTemplateLayoutCell

    您应该能够为 uicollectionview 切换图像视图。

    在他的表格视图中 - 而不是使用开箱即用的估计行高 - 你需要像

    这样的东西
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return [tableView fd_heightForCellWithIdentifier:@"FDFeedCell" configuration:^(FDFeedCell *cell) {
            cell.entity = self.feedEntities[indexPath.row];
        }];
    }
    
    
    
    #import "UITableView+FDTemplateLayoutCell.h"
    #import <objc/runtime.h>
    
    @implementation UITableView (FDTemplateLayoutCell)
    
    - (id)fd_templateCellForReuseIdentifier:(NSString *)identifier;
    {
        NSAssert(identifier.length > 0, @"Expects a valid identifier - %@", identifier);
    
        NSMutableDictionary *templateCellsByIdentifiers = objc_getAssociatedObject(self, _cmd);
        if (!templateCellsByIdentifiers) {
            templateCellsByIdentifiers = @{}.mutableCopy;
            objc_setAssociatedObject(self, _cmd, templateCellsByIdentifiers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
    
        UITableViewCell *templateCell = templateCellsByIdentifiers[identifier];
        if (!templateCell) {
            templateCell = [self dequeueReusableCellWithIdentifier:identifier];
            templateCellsByIdentifiers[identifier] = templateCell;
        }
    
        return templateCell;
    }
    
    - (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier configuration:(void (^)(id))configuration
    {
        // Fetch a cached template cell for `identifier`.
        UITableViewCell *cell = [self fd_templateCellForReuseIdentifier:identifier];
    
        // Reset to initial height as first created, otherwise the cell's height wouldn't retract if it
        // had larger height before it gets reused.
        cell.contentView.bounds = CGRectMake(0, 0, CGRectGetWidth(self.frame), self.rowHeight);
    
        // Manually calls to ensure consistent behavior with actual cells (that are displayed on screen).
        [cell prepareForReuse];
    
        // Customize and provide content for our template cell.
        if (configuration) {
            configuration(cell);
        }
    
        // Add a hard width constraint to make dynamic content views (like labels) expand vertically instead
        // of growing horizontally, in a flow-layout manner.
        NSLayoutConstraint *tempWidthConstraint =
        [NSLayoutConstraint constraintWithItem:cell.contentView
                                     attribute:NSLayoutAttributeWidth
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:nil
                                     attribute:NSLayoutAttributeNotAnAttribute
                                    multiplier:1.0
                                      constant:CGRectGetWidth(self.frame)];
        [cell.contentView addConstraint:tempWidthConstraint];
    
        // Auto layout does its math
        CGSize fittingSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    
        [cell.contentView removeConstraint:tempWidthConstraint];
    
        // Add 1px extra space for separator line if needed, simulating default UITableViewCell.
        if (self.separatorStyle != UITableViewCellSeparatorStyleNone) {
            fittingSize.height += 1.0 / [UIScreen mainScreen].scale;
        }
    
        return fittingSize.height;
    }
    
    @end
    

    【讨论】:

      【解决方案3】:

      根据我在设置 collectionView 单元格和大小的代码中可以理解的内容,在我看来,您希望拥有方形集合单元格,并且有 4 行,每行 7 个单元格,并且完全可见。

      如果您将约束添加到单元格中的collectionView 到所有4 个边距(顶部、底部、左侧和右侧),然后将7:4 的纵横比约束添加到collectionView,tableview 应该能够计算单元格高度会自动为您选择合适的尺寸。

      【讨论】:

      • 这会导致约束冲突。我还需要调整项目以填充所有可用空间 - 每个单元格之间不应该有任何间距。
      • 您必须相应地设置 tableView 单元格高度才能摆脱冲突的约束。当您运行它时,tableView 将调整单元格的大小,但在 IB 中您必须这样做。使用 7:4 的比例来计算应该不难。要让项目填满所有可用空间,您需要为 collectionView 设置 itemSize。但是注意,每个单元格中都有一个collectionView,所以你必须在tableView数据源的其中一个函数中设置它。
      • 这让我想到,你试图通过嵌入 tableview 单元格中的 collectionViews 实现的目标,可以通过一个 collectionView 以及你要在每个 tableView 单元格中放置的内容更容易完成在 CollectionView 的部分中。
      • 我不认为我们在同一页上。我在一个 UITableViewCell 中只有一个 UICollectionView,当然屏幕上还有其他表格视图单元格。
      • 你是对的。我错误地认为每个单元格中都有一个 collectionView。但我的回答仍然适用于您的问题。
      猜你喜欢
      • 2016-11-10
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多