使用自动布局时如何知道 UITableViewCell 的宽度?

Posted

技术标签:

【中文标题】使用自动布局时如何知道 UITableViewCell 的宽度?【英文标题】:How to know the width of an UITableViewCell when using auto layout? 【发布时间】:2015-07-07 09:19:21 【问题描述】:

我有一个UITableViewCell,我使用自动布局在其中放入了contentView 标签和其他内容。我添加了约束,其中之一是 contentViewUITableViewCell 具有相同的边界。

(在storyboard上,为了方便,我选择iphone 4-inch作为simulated metrics的大小。)

添加约束后,我调用layoutIfNeeded,因为我需要获取单元格的大小。我可以看到我的contentView 现在的大小与UITableViewCell 的大小相同。问题是UITableViewCell 的大小还没有适应屏幕的大小(我想它稍后会自动完成,因为我的单元格很好)。所以我仍然是 iphone 4 英寸的尺寸,而我使用的是 iphone 4.7 英寸。

有没有办法像使用layoutIfNeed 强制布局一样触发我的单元格的最终大小?

【问题讨论】:

什么时候调用layoutIfNeed方法? func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell中添加约束之后 我认为该单元格的超级视图当时为零。所以单元格的宽度不会更新为 tableView 的宽度。 实际上是我在故事板中的大小 是的,在添加到 tableView 之前它是默认大小。那么你为什么要获得 UITableViewCell 的宽度呢? 【参考方案1】:

当您从情节提要或笔尖加载单元格时,它在笔尖中具有指定的大小,而不是最后一个。在cellForRowAtIndexPath 中将您的视图和约束添加到contentView,然后通过cell.width = tableView.width 调整宽度。最后,像以前一样拨打layoutIfNeeded

这将导致单元格宽度正确的完整布局。

编辑:这是因为即使您在加载 nib 时启用了自动布局 (translatesAutoresizingMasksIntoConstraints = NO),但每个 nib 文件的第一个视图始终禁用自动布局 (translatesAutoresizingMasksIntoConstraints = YES)。

这意味着在渲染视图时(这样做layoutIfNeeded),自动布局将考虑实际的框架和掩码属性来确定正确的大小。

【讨论】:

感谢它的工作。只需要在 `layoutSubviews`` 方法中更新我的视图大小 这是一个非常烦人的问题。感谢您的回答!【参考方案2】:

添加约束后无需调用 layoutIfNeeded。

您可以子类化您的单元格并覆盖 - (void)layoutSubviews 方法以获取帧更改,或者如果您不想子类化,您可以将观察者添加到单元格。

[cell addObserver:yourObserver forKeyPath:@"self.frame" options:NSKeyValueObservingOptionNew context:NULL];

然后,在观察者的课堂上

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
    if(object==cell && [keyPath isEqualToString:@"self.frame"]) 
        //your code...
    

如果不起作用,请尝试将单元格替换为 cell.contentView。

编辑:如果您想通过使用与单元格高度匹配且宽度为 100 且与单元格左对齐的约束来创建子视图。

UIView *createdSubview = [[UIView alloc] init];
createdSubview.translatesAutoresizingMaskIntoConstraints = NO;
[cell.contentView addSubview:createdSubview];

//Left align
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[createdSubview]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];

// Fit the parent view height
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[createdSubview]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];

// Width constraint
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[createdSubview(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];

【讨论】:

但是在调用layoutIfNeeded 之后,我向我的单元格添加了一些子视图,如果我在layoutSubviews 中这样做,我会得到一个无限循环 你没有说你正在添加子视图。当然你不能在 layoutSubviews 中添加子视图,因为它会随着子视图的变化而重新触发方法。 但我不明白为什么你需要等到你的单元格达到最终大小才能添加子视图。为什么不在情节提要中创建它们,或者在加载视图之后创建它们?如果您正确设置了约束,您可以随时修改它们。 我不想为这些子视图添加约束,因为我会让它们与单元格相同的高度和固定宽度。我在创建单元格时以编程方式创建它们 最好的还是使用约束。我更新了我的答案,以便您可以看到如何添加带有约束的子视图。

以上是关于使用自动布局时如何知道 UITableViewCell 的宽度?的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局更改方向时更改内容顺序

如何在代码中获取自动布局中使用的标准间距值?

使用自动布局舍入视图?

使用自动布局删除和重新添加子视图

如何使用自动布局 beta 7 UIKIT 修复 xcode 11 中可滚动内容大小的歧义

自动布局比例间距