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

本文翻译自: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上的示例项目:

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 contentView
    CGFloat 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 样例项目

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:firstItem
                                 attribute:cellConstraint.firstAttribute
                                 relatedBy:cellConstraint.relation
                                    toItem:seccondItem
                                 attribute:cellConstraint.secondAttribute
                                multiplier:cellConstraint.multiplier
                                  constant: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中引入的动态调整大小。

发布了0 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/p15097962069/article/details/105220118