iOS8:可以对静态单元格使用“tableview.rowHeight = UITableViewAutomaticDimension”吗?

Posted

技术标签:

【中文标题】iOS8:可以对静态单元格使用“tableview.rowHeight = UITableViewAutomaticDimension”吗?【英文标题】:iOS8: Possible to use "tableview.rowHeight = UITableViewAutomaticDimension" for static cells? 【发布时间】:2014-10-01 08:13:13 【问题描述】:

我有一个 UITableView,它有五个静态单元格。我需要一个单元格的单元格高度自动调整到它的内容,这是一个 UILabel。

有什么办法可以用吗..

tableView.estimatedRowHeight = 42.0
tableView.rowHeight = UITableViewAutomaticDimension

..对于带有静态单元格的表格视图,还是仅适用于带有动态原型单元格的表格视图?

(或者有没有其他推荐的方法?)

其他信息

UITableView 位于嵌入到容器视图中的 TableViewController 中。

五个静态单元格彼此完全不同,并且只在一个应用场景中使用,所以我认为动态原型和自定义单元格子类没有多大意义。

我像这样更新表格视图

-(void) viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    [_myTableView reloadData];

我向 UILabel 添加了约束,如下所述: http://www.appcoda.com/self-sizing-cells/

【问题讨论】:

你发现更多了吗?因为我还想将UITableViewAutomaticDimension 与静态 TableView 一起使用... @Georg,看看我的回答。 我发布了一个answer,它显示了静态UITableViewCell 使用 Swift 3 自动调整其高度以适应其内容的 4 种不同方式。 【参考方案1】:

对于 ios 8,我发现您不能执行与 Dynamic Table View Cell 相同的策略。

为了自动调整静态单元格的高度,我实现了这两个 UITableViewDelegate 方法:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    return UITableViewAutomaticDimension;


-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

    return 44;

希望对你有帮助。

【讨论】:

我花了一整天的时间试图弄清楚这一点!非常感谢!哦,请注意:在这种情况下,自定义行高不再起作用,因此您必须设置所有约束,以便它们派生单元格高度。例如:我有一个带有固定大小容器视图的单元格,为此我设置了“超级视图中的中心 y”约束,并为单元格添加了自定义高度。自定义高度被忽略了,因此我不得不删除“中心 y”约束并添加顶部和底部间距约束。 :) 我在 iOS 9 上对其进行了测试,您可以在 UITableViewAutomaticDimension 中使用自定义高度,在方法 heightForRowAtIndexPath 返回您需要的行的自定义高度,在其他情况下返回 UITableViewAutomaticDimension。【参考方案2】:

扩展 Victors 的回答,一旦实现了以下委托,基于静态单元格的表格视图似乎会根据内容和约束自动调整单元格大小:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    return UITableViewAutomaticDimension;


-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

    return 44;

除非有标签。出于某种原因,标签固有内容高度似乎对单元格的高度计算没有贡献。我目前的解决方法是将标签嵌套在 UIView 中。

执行以下操作:

    在视图中嵌入标签(或多个标签)。 (选择 IB 上的标签并点击菜单 > 编辑器 > 嵌入 > 视图) 在此之间建立水平和垂直边距约束 视图和单元格 在您的 标签和此视图。

当然感觉像是一个 hack,但在我尝试过的所有情况下都对我有用。

【讨论】:

【参考方案3】:

最终这样做了。不是我想要的,但它适合我的简单要求和文本长度。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.row == 2)
    
        CGFloat padding = 30.0f;

        CGFloat labelWidth = self.tableView.bounds.size.width - padding*2;
        NSAttributedString *text = [[NSAttributedString alloc] initWithString:_freeTextLabel.text];
        NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin;
        CGRect boundingRect = [text boundingRectWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX)
                                             options:options
                                             context:nil];

        return (CGFloat) (ceil(boundingRect.size.height) + padding*2);
    
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];

【讨论】:

【参考方案4】:

注意:这是基于 @CamelBase 的答案,该答案是为 Objective-C 编写的,因此对于那些进行了转换但仍然难以自己转换东西的人来说,这主要是转换为 Swift。


对于那些想要使用 Swift 执行此操作并且想要一个包含静态单元格的表格的人,这里有一个可行的解决方案。

我不需要使用此代码(尝试将其放入 viewDidLoad() 并尝试不使用,没有任何区别):

tableView.estimatedRowHeight = 42.0
tableView.rowHeight = UITableViewAutomaticDimension

首先,您要将UILabel 添加到您希望自动增长内容的每个单元格中。

您需要向 UILabel 添加 4 个约束,所有这些约束都相对于父级(单元格的内容视图)。

领先优势 0 尾随保证金 0 上边距 0 下边距 0

这将使标签在单元格增长时增长(我们下面的代码就是这样做的)。

现在只需添加以下代码:

override func tableView(tableView: UITableView, 
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 

    let sectionICareAbout = 2
    let rowICareAbout = 1

    // repeat for as many section/row combos you need dynamic sizing on
    if indexPath.section == sectionICareAbout 
      && indexPath == rowICareAbout 
        // replace with how you get the content for the cell
        // in section 2 row 1
        let text = "line1\nline2\nline3"
        return rowHeightForText(text)
    

    // use auto-dimension if we didn't set something else
    return UITableViewAutomaticDimension


func rowHeightForText(text: String) -> CGFloat 
    let labelWidth = tableView.bounds.size.width
    let attributedText = NSAttributedString(string: text)
    let options = NSStringDrawingOptions.UsesLineFragmentOrigin
    let size = CGSize(width: labelWidth, height: CGFloat.max)
    let boundingRect = attributedText.boundingRectWithSize(size, 
        options: options, context: nil)
    return boundingRect.size.height

【讨论】:

【参考方案5】:

在 IOS8 中,我发现在代码中显式设置行高/宽度或标签高度/宽度会导致比它修复的问题更多。我已经使用自动布局创建了具有不同单元格高度和多行标签的动态和静态表格,但是您确实必须严格遵守 Apple 标准,否则会发生奇怪的事情(例如分隔符消失或行高度随机折叠)。

[已编辑] 在 UITableViewDelegate 中将estimatedHeightForRowAtIndexPath heightForRowAtIndexPath 设置为自动尺寸

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return UITableViewAutomaticDimension

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return UITableViewAutomaticDimension

确保单元格中的每个元素都有一个上/下/左/右 = 约束(不是 >=、

【讨论】:

【参考方案6】:

这是一个使用 Swift 3 的简单示例。我们在 Storyboard 中设置了一个 UITableViewController,其类型为 grouped,内容类型为 static 单元格。它的tableView 包含一个UITableViewCell。该单元格包含一个UILabel,其中有许多行设置为0,并显示了一些很长的文本。该标签还具有四个自动布局约束,其 superViewtopbottomleadingtrailing) .

现在,您可以选择以下四个代码 sn-ps 之一,以允许您的静态单元格根据其内容自动调整大小。


#1。使用tableView(_:estimatedHeightForRowAt:)tableView(_:heightForRowAt:)

注意:tableView(_:estimatedHeightForRowAt:) 方法需要 iOS7

import UIKit

class TableViewController: UITableViewController 

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        return UITableViewAutomaticDimension
    

    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat 
        return 100 // Return `UITableViewAutomaticDimension` if you have no estimate
    



#2。使用estimatedRowHeight 属性和tableView(_:heightForRowAt:)

注意:estimatedRowHeight 属性需要 iOS7

import UIKit

class TableViewController: UITableViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.estimatedRowHeight = 100
    

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        return UITableViewAutomaticDimension
    



#3。使用tableView(_:heightForRowAt:)

import UIKit

class TableViewController: UITableViewController 

    // Bind this IBOutlet to the cell in Storyboard
    @IBOutlet weak var cell: UITableViewCell!

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        let fittingSize = CGSize(width: tableView.bounds.size.width, height: 0)
        let systemLayoutSize = cell.systemLayoutSizeFitting(fittingSize, withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel)
        return systemLayoutSize.height
    



#4。使用UITableViewCell 子类和tableView(_:heightForRowAt:)

import UIKit

class TableViewController: UITableViewController 

    // 1. Set custom class to `CustomCell` for cell in Storyboard
    // 2. Bind this IBOutlet to the cell in Storyboard
    @IBOutlet weak var cell: CustomCell!

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        cell.layoutIfNeeded()
        let contentViewSize = cell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
        return contentViewSize.height + 1 // + 1 for the separator
    



class CustomCell: UITableViewCell 

    // 1. Set custom class to `CustomCell` for cell in Storyboard
    // 2. Bind this IBOutlet to the cell's label in Storyboard
    @IBOutlet weak var label: UILabel!

    override func layoutSubviews() 
        super.layoutSubviews()
        label.preferredMaxLayoutWidth = frame.width
    



之前的所有四个代码 sn-ps 都会导致如下显示:

【讨论】:

【参考方案7】:

我假设我需要告诉单元格使用类似的东西重绘

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];

当涉及到动态改变 tableviewcells 的高度时。

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
return Yourvalue; //return whatever u want ur cell to have size.
  

【讨论】:

感谢您的回答。我无法让重绘工作,但我会进一步研究。对于 heightForRowAtIndexPath,我认为静态单元格不会调用该方法,但我错了。然而,它确实需要一些尺寸计算(如 here 所示),这就是我最初想使用 UITableViewAutomaticDimension 的原因 设法让 reloadRowsAtIndexPaths 运行没有错误,但它不能解决问题。无论如何感谢@DorusJanssens!【参考方案8】:

我也在寻找这个问题的答案并找到了这个解决方案,我在 iOS8 中测试并完美运行。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    if (indexPath.row == 2)  //Dynamic Height
    
        return UITableViewAutomaticDimension;
    
    else 
    
        return 50;  // Static Height
    

【讨论】:

以上是关于iOS8:可以对静态单元格使用“tableview.rowHeight = UITableViewAutomaticDimension”吗?的主要内容,如果未能解决你的问题,请参考以下文章

设置静态表格视图单元格的复选标记

将数据从容器视图中的 tableview 中的静态单元格发送到 Swift 中的视图控制器

iOS 8 中 TableView 单元格编辑控件的问题

在 iOS8 的 Interface Builder 中向 UITableView 添加静态单元格?内容部分未显示

如何将静态单元格快速拖动到 tableView 中?

将 JSON 解析为 TableView xcode 6.0.1,iOS8