本文翻译自:Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

如何在表格视图的UITableViewCell使用自动布局,以使每个单元格的内容和子视图确定行高(自身/自动),同时保持流畅的滚动性能?


#1楼

参考:https://stackoom.com/question/1Gevp/在UITableView中使用自动布局以获取动态单元格布局和可变的行高


#2楼

TL;DR: Don't like reading? TL; DR:不喜欢阅读? Jump straight to the sample projects on GitHub: 直接跳转到GitHub上的示例项目:

  • iOS 8 Sample Project - Requires iOS 8 iOS 8示例项目 -需要iOS 8
  • iOS 7 Sample Project - Works on iOS 7+ iOS 7示例项目 -适用于iOS 7+

Conceptual Description 概念描述

The first 2 steps below are applicable regardless of which iOS versions you are developing for. 无论您针对哪个iOS版本开发,以下前两个步骤均适用。

1. Set Up & Add Constraints 1.设置和添加约束

In your UITableViewCell subclass, add constraints so that the subviews of the cell have their edges pinned to the edges of the cell's contentView (most importantly to the top AND bottom edges). UITableViewCell子类中,添加约束,以使单元格的子视图的边缘固定到单元格contentView的边缘(最重要的是顶部和底部边缘)。 NOTE: don't pin subviews to the cell itself; 注意:不要将子视图固定到单元格本身; only to the cell's contentView ! 仅对单元格的contentView Let the intrinsic content size of these subviews drive the height of the table view cell's content view by making sure the content compression resistance and content hugging constraints in the vertical dimension for each subview are not being overridden by higher-priority constraints you have added. 让这些子视图的固有内容大小驱动表格视图单元格的内容视图的高度,方法是确保每个子视图的垂直方向的内容压缩阻力内容拥抱约束都不会被添加的更高优先级约束所覆盖。 ( Huh? Click here. ) ( 嗯?点击这里。 )

Remember, the idea is to have the cell's subviews connected vertically to the cell's content view so that they can "exert pressure" and make the content view expand to fit them. 请记住,其想法是使单元的子视图垂直连接到单元的内容视图,以便它们可以“施加压力”并使内容视图扩展以适合它们。 Using an example cell with a few subviews, here is a visual illustration of what some (not all!) of your constraints would need to look like: 使用带有几个子视图的示例单元格,这是一些 (不是全部!)约束看起来像的视觉插图:

You can imagine that as more text is added to the multi-line body label in the example cell above, it will need to grow vertically to fit the text, which will effectively force the cell to grow in height. 您可以想象,随着在上面的示例单元格中将更多文本添加到多行主体标签中,它将需要垂直增长以适合文本,这将有效地迫使单元格高度增加。 (Of course, you need to get the constraints right in order for this to work correctly!) (当然,您需要正确设置约束条件才能使其正常工作!)

Getting your constraints right is definitely the hardest and most important part of getting dynamic cell heights working with Auto Layout. 正确使用约束绝对是使用自动版式获得动态像元高度时最困难也是最重要的部分 。 If you make a mistake here, it could prevent everything else from working -- so take your time! 如果您在此处输入错误,则可能会阻止其他所有功能运行-因此,请花点时间! I recommend setting up your constraints in code because you know exactly which constraints are being added where, and it's a lot easier to debug when things go wrong. 我建议您在代码中设置约束,因为您确切知道要在哪里添加约束,并且在出现问题时调试起来要容易得多。 Adding constraints in code can be just as easy as and significantly more powerful than Interface Builder using layout anchors, or one of the fantastic open source APIs available on GitHub. 与使用布局锚点或GitHub上一种出色的开源API之一的Interface Builder相比,在代码中添加约束既简单又强大,而且功能强大。

  • If you're adding constraints in code, you should do this once from within the updateConstraints method of your UITableViewCell subclass. 如果要在代码中添加约束,则应在UITableViewCell子类的updateConstraints方法中执行一次。 Note that updateConstraints may be called more than once, so to avoid adding the same constraints more than once, make sure to wrap your constraint-adding code within updateConstraints in a check for a boolean property such as didSetupConstraints (which you set to YES after you run your constraint-adding code once). 请注意, updateConstraints可能会被调用多次,因此,为避免多次添加相同的约束,请确保将检查添加约束的代码包装在updateConstraints中,以检查是否有布尔值属性,例如didSetupConstraints (设置为YES后,一次运行添加约束的代码)。 On the other hand, if you have code that updates existing constraints (such as adjusting the constant property on some constraints), place this in updateConstraints but outside of the check for didSetupConstraints so it can run every time the method is called. 另一方面,如果您有更新现有约束的代码(例如,在某些约束上调整constant属性),请将其放置在updateConstraints但不在didSetupConstraints的检查范围之内,因此它可以在每次调用该方法时运行。

2. Determine Unique Table View Cell Reuse Identifiers 2.确定唯一的表视图单元重用标识符

For every unique set of constraints in the cell, use a unique cell reuse identifier. 对于单元中的每个唯一约束集,请使用唯一的单元重用标识符。 In other words, if your cells have more than one unique layout, each unique layout should receive its own reuse identifier. 换句话说,如果您的单元具有多个唯一的布局,则每个唯一的布局应收到其自己的重用标识符。 (A good hint that you need to use a new reuse identifier is when your cell variant has a different number of subviews, or the subviews are arranged in a distinct fashion.) (当单元变体具有不同数量的子视图,或者子视图以不同的方式排列时,就需要使用新的重用标识符。)

For example, if you were displaying an email message in each cell, you might have 4 unique layouts: messages with just a subject, messages with a subject and a body, messages with a subject and a photo attachment, and messages with a subject, body, and photo attachment. 例如,如果您在每个单元格中显示一封电子邮件,则可能有4种独特的布局:仅包含主题的邮件,包含主题和正文的邮件,包含主题和照片附件的邮件以及包含主题的邮件,机身和照片附件。 Each layout has completely different constraints required to achieve it, so once the cell is initialized and the constraints are added for one of these cell types, the cell should get a unique reuse identifier specific to that cell type. 每个布局具有实现它所需的完全不同的约束,因此,一旦初始化了单元并为这些单元类型之一添加了约束,该单元就应获得特定于该单元类型的唯一重用标识符。 This means when you dequeue a cell for reuse, the constraints have already been added and are ready to go for that cell type. 这意味着当您使单元出队以供重用时,约束已被添加并且可以用于该单元类型。

Note that due to differences in intrinsic content size, cells with the same constraints (type) may still have varying heights! 请注意,由于内部内容大小的不同,具有相同约束(类型)的单元格可能仍具有不同的高度! Don't confuse fundamentally different layouts (different constraints) with different calculated view frames (solved from identical constraints) due to different sizes of content. 不要将根本不同的布局(不同的约束)与由于内容大小不同而导致的计算出的不同视图框(由相同约束解决)混淆。

  • Do not add cells with completely different sets of constraints to the same reuse pool (ie use the same reuse identifier) and then attempt to remove the old constraints and set up new constraints from scratch after each dequeue. 不要在完全相同的重用池中添加具有完全不同的约束集的单元(即使用相同的重用标识符),然后在每次出队后尝试删除旧约束并从头开始设置新约束。 The internal Auto Layout engine is not designed to handle large scale changes in constraints, and you will see massive performance issues. 内部的自动版图引擎并非旨在处理约束的大规模变化,您将看到大量的性能问题。

For iOS 8 - Self-Sizing Cells 对于iOS 8-自定义单元格

3. Enable Row Height Estimation 3.启用行高估算

To enable self-sizing table view cells, you must set the table view's rowHeight property to UITableViewAutomaticDimension. 要启用自动调整大小的表格视图单元格,必须将表格视图的rowHeight属性设置为UITableViewAutomaticDimension。 You must also assign a value to the estimatedRowHeight property. 您还必须将一个值分配给estimatedRowHeight属性。 As soon as both of these properties are set, the system uses Auto Layout to calculate the row's actual height 一旦设置了这两个属性,系统就会使用“自动布局”来计算行的实际高度

Apple: Working with Self-Sizing Table View Cells 苹果: 使用自动调整大小的表格视图单元

With iOS 8, Apple has internalized much of the work that previously had to be implemented by you prior to iOS 8. In order to allow the self-sizing cell mechanism to work, you must first set the rowHeight property on the table view to the constant UITableViewAutomaticDimension . 对于iOS 8,Apple已将以前必须由您在iOS 8之前执行的大部分工作内部化。为了使自定义单元格功能正常工作,必须首先将表格视图上的rowHeight属性设置为常量UITableViewAutomaticDimension Then, you simply need to enable row height estimation by setting the table view's estimatedRowHeight property to a nonzero value, for example: 然后,您只需将表视图的estimatedRowHeight属性设置为非零值即可启用行高估计,例如:

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0; // set to whatever your "average" cell height is

What this does is provide the table view with a temporary estimate/placeholder for the row heights of cells that are not yet onscreen. 这是为表格视图提供临时估计/占位符,用于尚未显示在屏幕上的单元格的行高。 Then, when these cells are about to scroll on screen, the actual row height will be calculated. 然后,当这些单元格即将在屏幕上滚动时,将计算实际的行高。 To determine the actual height for each row, the table view automatically asks each cell what height its contentView needs to be based on the known fixed width of the content view (which is based on the table view's width, minus any additional things like a section index or accessory view) and the auto layout constraints you have added to the cell's content view and subviews. 为了确定每一行的实际高度,表格视图会自动询问每个单元格其contentView需要基于已知的内容视图固定宽度(该高度基于表格视图的宽度,减去部分之类的其他东西)的高度索引或附件视图)以及已添加到单元格内容视图和子视图的自动布局约束。 Once this actual cell height has been determined, the old estimated height for the row is updated with the new actual height (and any adjustments to the table view's contentSize/contentOffset are made as needed for you). 确定此实际单元格高度后,将使用新的实际高度更新该行的旧估计高度(并根据需要对表视图的contentSize / contentOffset进行任何调整)。

Generally speaking, the estimate you provide doesn't have to be very accurate -- it is only used to correctly size the scroll indicator in the table view, and the table view does a good job of adjusting the scroll indicator for incorrect estimates as you scroll cells onscreen. 一般而言,您提供的估算值不一定非常准确-仅用于在表格视图中正确调整滚动指示器的大小,而表格视图在调整滚动指示器以适应您估算的不正确估算方面做得很好滚动屏幕上的单元格。 You should set the estimatedRowHeight property on the table view (in viewDidLoad or similar) to a constant value that is the "average" row height. 你应该设置estimatedRowHeight上表视图(物业viewDidLoad或类似),以一个恒定值,是“平均”行高。 Only if your row heights have extreme variability (eg differ by an order of magnitude) and you notice the scroll indicator "jumping" as you scroll should you bother implementing tableView:estimatedHeightForRowAtIndexPath: to do the minimal calculation required to return a more accurate estimate for each row. 仅当行高具有极大的可变性(例如,相差一个数量级)并且您在滚动时注意到滚动指示器“跳跃”时,才应该麻烦实现tableView:estimatedHeightForRowAtIndexPath:来执行为返回更准确的估算所需的最小计算每一行。

For iOS 7 support (implementing auto cell sizing yourself) 对于iOS 7支持(自行实现自动调整大小)

3. Do a Layout Pass & Get The Cell Height 3.进行布局通过并获取像元高度

First, instantiate an offscreen instance of a table view cell, one instance for each reuse identifier , that is used strictly for height calculations. 首先,实例化一个表格视图单元格的屏幕外实例, 每个重用标识符一个实例该实例严格用于高度计算。 (Offscreen meaning the cell reference is stored in a property/ivar on the view controller and never returned from tableView:cellForRowAtIndexPath: for the table view to actually render onscreen.) Next, the cell must be configured with the exact content (eg text, images, etc) that it would hold if it were to be displayed in the table view. (屏幕外表示单元格引用存储在视图控制器上的属性/ ivar中,从不从tableView:cellForRowAtIndexPath:返回,以使表格视图实际呈现在屏幕上。)接下来,必须为单元格配置确切的内容(例如,文本,图片等),以便将其显示在表格视图中。

Then, force the cell to immediately layout its subviews, and then use the systemLayoutSizeFittingSize: method on the UITableViewCell 's contentView to find out what the required height of the cell is. 然后,强制该单元立即布置其子视图,然后在UITableViewCellcontentView上使用systemLayoutSizeFittingSize:方法来找出所需的单元高度。 Use UILayoutFittingCompressedSize to get the smallest size required to fit all the contents of the cell. 使用UILayoutFittingCompressedSize可获得适合单元格所有内容的最小尺寸。 The height can then be returned from the tableView:heightForRowAtIndexPath: delegate method. 然后可以从tableView:heightForRowAtIndexPath:委托方法返回高度。

4. Use Estimated Row Heights 4.使用估计的行高

If your table view has more than a couple dozen rows in it, you will find that doing the Auto Layout constraint solving can quickly bog down the main thread when first loading the table view, as tableView:heightForRowAtIndexPath: is called on each and every row upon first load (in order to calculate the size of the scroll indicator). 如果您的表视图中包含多于几十行,您会发现执行自动布局约束解决方案可以在首次加载表视图时快速使主线程陷入困境,因为在每一行上都调用tableView:heightForRowAtIndexPath:第一次加载时(为了计算滚动指示器的大小)。

As of iOS 7, you can (and absolutely should) use the estimatedRowHeight property on the table view. 从iOS 7开始,您可以(绝对应该)在表格视图上使用estimatedRowHeight属性。 What this does is provide the table view with a temporary estimate/placeholder for the row heights of cells that are not yet onscreen. 这是为表格视图提供临时估计/占位符,用于尚未显示在屏幕上的单元格的行高。 Then, when these cells are about to scroll on screen, the actual row height will be calculated (by calling tableView:heightForRowAtIndexPath: ), and the estimated height updated with the actual one. 然后,当这些单元格即将在屏幕上滚动时,将计算实际行高(通过调用tableView:heightForRowAtIndexPath: ,并使用实际值更新估计的高度。

Generally speaking, the estimate you provide doesn't have to be very accurate -- it is only used to correctly size the scroll indicator in the table view, and the table view does a good job of adjusting the scroll indicator for incorrect estimates as you scroll cells onscreen. 一般而言,您提供的估算值不一定非常准确-仅用于在表格视图中正确调整滚动指示器的大小,而表格视图在调整滚动指示器以适应您估算的不正确估算方面做得很好滚动屏幕上的单元格。 You should set the estimatedRowHeight property on the table view (in viewDidLoad or similar) to a constant value that is the "average" row height. 你应该设置estimatedRowHeight上表视图(物业viewDidLoad或类似),以一个恒定值,是“平均”行高。 Only if your row heights have extreme variability (eg differ by an order of magnitude) and you notice the scroll indicator "jumping" as you scroll should you bother implementing tableView:estimatedHeightForRowAtIndexPath: to do the minimal calculation required to return a more accurate estimate for each row. 仅当行高具有极大的可变性(例如,相差一个数量级)并且您在滚动时注意到滚动指示器“跳跃”时,才应该麻烦实现tableView:estimatedHeightForRowAtIndexPath:来执行为返回更准确的估算所需的最小计算每一行。

5. (If Needed) Add Row Height Caching 5.(如果需要)添加行高缓存

If you've done all the above and are still finding that performance is unacceptably slow when doing the constraint solving in tableView:heightForRowAtIndexPath: , you'll unfortunately need to implement some caching for cell heights. 如果您已完成上述所有操作,但在tableView:heightForRowAtIndexPath:进行约束求解时仍然发现性能降低得令人无法接受,那么您将需要为单元格高度实现一些缓存。 (This is the approach suggested by Apple's engineers.) The general idea is to let the Autolayout engine solve the constraints the first time, then cache the calculated height for that cell and use the cached value for all future requests for that cell's height. (这是Apple工程师建议的方法。)一般的想法是让Autolayout引擎第一次解决约束,然后缓存该单元格的计算高度,并将缓存的值用于该单元格高度的所有将来请求。 The trick of course is to make sure you clear the cached height for a cell when anything happens that could cause the cell's height to change -- primarily, this would be when that cell's content changes or when other important events occur (like the user adjusting the Dynamic Type text size slider). 当然,技巧是确保在发生任何可能导致单元格高度发生变化的事件时清除单元格的缓存高度-主要是,这是在该单元格的内容发生更改或其他重要事件发生时(例如用户调整动态类型文字大小滑块)。

iOS 7 Generic Sample Code (with lots of juicy comments) iOS 7通用示例代码(有很多多汁的注释)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{// Determine which reuse identifier should be used for the cell at this // index path, depending on the particular layout required (you may have// just one, or may have many).NSString *reuseIdentifier = ...;// Dequeue a cell for the reuse identifier.// Note that this method will init and return a new cell if there isn't// one available in the reuse pool, so either way after this line of // code you will have a cell with the correct constraints ready to go.UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];// Configure the cell with content for the given indexPath, for example:// cell.textLabel.text = someTextForThisCell;// ...// Make sure the constraints have been set up for this cell, since it // may have just been created from scratch. Use the following lines, // assuming you are setting up constraints from within the cell's // updateConstraints method:[cell setNeedsUpdateConstraints];[cell updateConstraintsIfNeeded];// If you are using multi-line UILabels, don't forget that the // preferredMaxLayoutWidth needs to be set correctly. Do it at this // point if you are NOT doing it within the UITableViewCell subclass // -[layoutSubviews] method. For example: // cell.multiLineLabel.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds);return cell;
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{// Determine which reuse identifier should be used for the cell at this // index path.NSString *reuseIdentifier = ...;// Use a dictionary of offscreen cells to get a cell for the reuse // identifier, creating a cell and storing it in the dictionary if one // hasn't already been added for the reuse identifier. WARNING: Don't // call the table view's dequeueReusableCellWithIdentifier: method here // because this will result in a memory leak as the cell is created but // never returned from the tableView:cellForRowAtIndexPath: method!UITableViewCell *cell = [self.offscreenCells objectForKey:reuseIdentifier];if (!cell) {cell = [[YourTableViewCellClass alloc] init];[self.offscreenCells setObject:cell forKey:reuseIdentifier];}// Configure the cell with content for the given indexPath, for example:// cell.textLabel.text = someTextForThisCell;// ...// Make sure the constraints have been set up for this cell, since it // may have just been created from scratch. Use the following lines, // assuming you are setting up constraints from within the cell's // updateConstraints method:[cell setNeedsUpdateConstraints];[cell updateConstraintsIfNeeded];// Set the width of the cell to match the width of the table view. This// is important so that we'll get the correct cell height for different// table view widths if the cell's height depends on its width (due to // multi-line UILabels word wrapping, etc). We don't need to do this // above in -[tableView:cellForRowAtIndexPath] because it happens // automatically when the cell is used in the table view. Also note, // the final width of the cell may not be the width of the table view in// some cases, for example when a section index is displayed along // the right side of the table view. You must account for the reduced // cell width.cell.bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));// Do the layout pass on the cell, which will calculate the frames for // all the views based on the constraints. (Note that you must set the // preferredMaxLayoutWidth on multiline UILabels inside the // -[layoutSubviews] method of the UITableViewCell subclass, or do it // manually at this point before the below 2 lines!)[cell setNeedsLayout];[cell layoutIfNeeded];// Get the actual height required for the cell's contentViewCGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;// Add an extra point to the height to account for the cell separator, // which is added between the bottom of the cell's contentView and the // bottom of the table view cell.height += 1.0;return height;
}// NOTE: Set the table view's estimatedRowHeight property instead of
// implementing the below method, UNLESS you have extreme variability in
// your row heights and you notice the scroll indicator "jumping"
// as you scroll.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{// Do the minimal calculations required to be able to return an // estimated row height that's within an order of magnitude of the // actual height. For example:if ([self isTallCellAtIndexPath:indexPath]) {return 350.0;} else {return 40.0;}
}

Sample Projects 样例项目

  • iOS 8 Sample Project - Requires iOS 8 iOS 8示例项目 -需要iOS 8
  • iOS 7 Sample Project - Works on iOS 7+ iOS 7示例项目 -适用于iOS 7+

These projects are fully working examples of table views with variable row heights due to table view cells containing dynamic content in UILabels. 这些项目是具有可变行高的表格视图的完全可用示例,这是由于表格视图单元格包含UILabels中的动态内容。

Xamarin (C#/.NET) Xamarin(C#/。NET)

If you're using Xamarin, check out this sample project put together by @KentBoogaart . 如果您使用的是Xamarin,请查看@KentBoogaart编写的此示例项目 。


#3楼

The solution proposed by @smileyborg is almost perfect. @smileyborg提出的解决方案几乎是完美的。 If you have a custom cell and you want one or more UILabel with dynamic heights then the systemLayoutSizeFittingSize method combined with AutoLayout enabled returns a CGSizeZero unless you move all your cell constraints from the cell to its contentView (as suggested by @TomSwift here How to resize superview to fit all subviews with autolayout? ). 如果您有一个自定义单元格,并且想要一个或多个具有动态高度的UILabel ,则将systemLayoutSizeFittingSize方法与AutoLayout结合使用会返回CGSizeZero除非您将所有单元格约束从该单元格移至其contentView(如@TomSwift此处所示, 如何调整大小)来让所有子视图都具有自动布局功能? )。

To do so you need to insert the following code in your custom UITableViewCell implementation (thanks to @Adrian). 为此,您需要在自定义UITableViewCell实现中插入以下代码(感谢@Adrian)。

- (void)awakeFromNib{[super awakeFromNib];for (NSLayoutConstraint *cellConstraint in self.constraints) {[self removeConstraint:cellConstraint];id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;NSLayoutConstraint *contentViewConstraint =[NSLayoutConstraint constraintWithItem:firstItemattribute:cellConstraint.firstAttributerelatedBy:cellConstraint.relationtoItem:seccondItemattribute:cellConstraint.secondAttributemultiplier:cellConstraint.multiplierconstant:cellConstraint.constant];[self.contentView addConstraint:contentViewConstraint];}
}

Mixing @smileyborg answer with this should works. 将@smileyborg答案与此混用应该可以。


#4楼

An important enough gotcha I just ran into to post as an answer. 我刚遇到要发布的答案就足够重要。

@smileyborg's answer is mostly correct. @smileyborg的答案基本上是正确的。 However, if you have any code in the layoutSubviews method of your custom cell class, for instance setting the preferredMaxLayoutWidth , then it won't be run with this code: 但是,如果您的自定义单元格类的layoutSubviews方法中包含任何代码(例如,设置preferredMaxLayoutWidth ,则它将无法与此代码一起运行:

[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];

It confounded me for awhile. 这让我有些困惑。 Then I realized it's because those are only triggering layoutSubviews on the contentView , not the cell itself. 然后我意识到这是因为这些仅触发contentView上的layoutSubviews,而不是单元格本身。

My working code looks like this: 我的工作代码如下所示:

TCAnswerDetailAppSummaryCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailAppSummaryCell"];
[cell configureWithThirdPartyObject:self.app];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;

Note that if you are creating a new cell, I'm pretty sure you don't need to call setNeedsLayout as it should already be set. 请注意,如果您要创建一个新的单元格,我很确定您不需要调用setNeedsLayout因为它应该已经设置。 In cases where you save a reference to a cell, you should probably call it. 如果您保存对单元格的引用,则可能应该调用它。 Either way it shouldn't hurt anything. 无论哪种方式,它都不会伤害任何东西。

Another tip if you are using cell subclasses where you are setting things like preferredMaxLayoutWidth . 另一个提示,如果您使用的是单元格子类,则在其中设置诸如preferredMaxLayoutWidth As @smileyborg mentions, "your table view cell hasn't yet had its width fixed to the table view's width". 正如@smileyborg所提到的,“您的表格视图单元格的宽度尚未固定为表格视图的宽度”。 This is true, and trouble if you are doing your work in your subclass and not in the view controller. 的确如此,如果您在子类中而不是在视图控制器中进行工作,那么会很麻烦。 However you can simply set the cell frame at this point using the table width: 但是,您可以在此时使用表格宽度简单地设置单元格框架:

For instance in the calculation for height: 例如在高度计算中:

self.summaryCell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailDefaultSummaryCell"];
CGRect oldFrame = self.summaryCell.frame;
self.summaryCell.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, self.tableView.frame.size.width, oldFrame.size.height);

(I happen to cache this particular cell for re-use, but that's irrelevant). (我碰巧要缓存此特定单元以供重复使用,但这无关紧要)。


#5楼

In case people are still having trouble with this. 如果人们仍然对此感到麻烦。 I wrote a quick blog post about using Autolayout with UITableViews Leveraging Autolayout For Dynamic Cell Heights as well as an open source component to help make this more abstract and easier to implement. 我写了一篇简短的博客文章,内容涉及将自动布局与UITableViews结合使用,以利用动态布局高度的自动布局以及一个开源组件来帮助使这一过程更加抽象和易于实现。 https://github.com/Raizlabs/RZCellSizeManager https://github.com/Raizlabs/RZCellSizeManager


#6楼

As long as your layout in your cell is good. 只要您在单元格中的布局良好即可。

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];return [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}

Update: You should use dynamic resizing introduced in iOS 8. 更新:您应该使用iOS 8中引入的动态调整大小。

在UITableView中使用自动布局以获取动态单元格布局和可变的行高相关推荐

  1. vsflexgrid单元格换行后自动使用行高_Excel表格不会换行?10个超实用Excel小技巧,用了都说好!...

    Hello,各位叨友们好呀!我是叨叨君~ 前几天有位叨友给我留言,让我讲讲关于Excel自动换行与强制换行的内容,说自己傻傻搞不清楚,所以今天就来跟大家唠唠关于Excel换行以及其它日常的小技巧,希望 ...

  2. sql 时间范围查询_Excel中使用SQL查询,单元格范围最多支持65536行?

    1.先建立一个excel,本人的版本为2016 2.然后向下填充数字,操作为填充--序列 这样生成1-66666的序列 3.使用SQL查询语句,进行查询 使用语句 : select 序列 from [ ...

  3. (智能间距换行均满足)Excel中单元格批量调整行间距,行高自动适应内容,且自动换行

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 步骤 一.操作步骤 1.打开EXCEL,选中要调整的单元列,点击开始菜单中的自动换行,换行成功后,点击格式中的自动调整行高 2.按al ...

  4. vsflexgrid单元格换行后自动使用行高_「Excel技巧」Excel关于换行的技巧,你懂多少?...

    今天话题,主要分享Excel换行的技巧.Excel单元格内换行,有自动换行和强制换行,批量强制换行.现在就来看看它们的区别及设置方式. 一.自动换行 自动换行的长度是根据单元格的列宽来定的,即单元格第 ...

  5. matlab excel 单元居中,用matlab如何识别excel里的单元格是否为合并单元格|excel表格怎么调整行高和列宽...

    用matlab合并excel表格文件 没看明白 你换一种表述说说 matlab怎么合并excel单元格并赋值? 需要确切地说明一下:matlab导入默认是double型的,小数点后至以保留15位.你不 ...

  6. elementUI表格中动态单元格合并

    关于动态单元格合并,官方文档提供的方法仅可实现相邻的两行数据合并,这里博主分享一下多行相同的数据也可以合并 结构代码 <el-table:span-method="objectSpan ...

  7. c语言mac地址加冒号,如何通过在Excel中添加冒号来格式化单元格中的mac地址?

    如何通过在Excel中添加冒号来格式化单元格中的mac地址? 假设您收到一个包含数字列表的工作表,现在您需要通过添加冒号将所有这些数字格式设置为mac地址,如下面的屏幕截图所示. 您能做什么来实现呢? ...

  8. 使用jquery合并表格中相同文本的相邻单元格

    一.效果 二.代码 <!DOCTYPE HTML> <html> <head><title>Example</title><meta ...

  9. jQuery: 合并表格中相同文本的相邻单元格

    一.效果 二.代码 <!DOCTYPE HTML> <html> <head><title>Example</title><meta ...

最新文章

  1. iOS 11开发教程(十一)了解iOS11应用视图
  2. GNOME 3.31.91 发布,3.32 发布周期第二个 beta 版
  3. c语言 函数的参数传递示例_nexttoward()函数以及C ++中的示例
  4. python自定义模块和三方模块_python基础知识8——模块1——自定义模块和第三方开源模块...
  5. IoT -- (六) MQTT和CoAP对比分析
  6. 聊聊Vue(前端Vue面试包过)【面试干货】
  7. Linux 内核 hlist_head,hlist_node
  8. Linux常用命令汇总 - Linux Shell Cheat Sheet
  9. 位置式数字PI控制器C语言
  10. MySQL系列:java个人简历模板word
  11. SOCKS5协议的原理和应用
  12. Excel操作:分析工具库
  13. mysql解题器_mysql触发器,答题记录表同步教学跟踪(用户列表)
  14. MongoDB快速入门学习
  15. 红包码收款码合二为一
  16. 5G技术在广播电视中的应用方式
  17. 浅谈动态规划 ——by cbw
  18. 一张表带你了解S3系列接触式芯片卡读写器的差异
  19. Linux环境下——实现xml文件解析
  20. 数学图形(1.7)圆内旋轮线

热门文章

  1. JavaBean用JSP调用和使用JSP动作标签的区别
  2. UnboundLocalError: local vaiable 'XX' reference...
  3. MySQL数据库基本用法-查询
  4. Android(java)学习笔记155:中文乱码的问题处理(qq登录案例)
  5. js中ajax的异步性
  6. 子查询三(在FROM子句中使用子查询)
  7. ImageMagick---import(截图)
  8. 信息系统项目管理师(高级)考试大纲
  9. 闭包 进阶 javascript
  10. zabbix 通过import批量导入新增主机和批量删除旧的主机