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

时间:2014-10-01 08:13:14

标签: ios uitableview ios8

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

我有什么方法可以使用..

tableView.estimatedRowHeight = 42.0
tableView.rowHeight = UITableViewAutomaticDimension

..对于带有静态单元格的表格视图,或者这仅适用于具有动态原型单元格的表格视图?

(或者你会推荐其他任何方式吗?)

其他信息

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

五个静态单元格彼此完全不同,仅在一个应用程序场景中使用,因此我没有看到动态原型和自定义单元格子类的重点。

我像这样更新tableview

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

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

8 个答案:

答案 0 :(得分:45)

对于iOS 8,我发现你不能采用与动态表视图单元相同的策略。

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

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

希望它有所帮助。

答案 1 :(得分:3)

扩展Victors的答案,基于静态单元格的表格视图似乎在实施以下代理后基于内容和约束自动调整单元格:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

除非有标签。由于某种原因,标签内在含量高度似乎没有对细胞的高度计算有贡献。我目前的工作是将标签嵌套在UIView中。

执行以下操作:

  1. 在视图中嵌入标签(或标签)。 (在IB上选择标签,然后按菜单>编辑器>嵌入>查看)
  2. 在此之间建立水平和垂直边距约束 查看和单元格
  3. 建立您之间的水平和垂直保证金约束 标签和这个观点。
  4. 当然,感觉就像一个黑客,但在我尝试的所有情况下都适合我。

答案 2 :(得分:1)

结束这样做。不是我想要的,但它对我的简单要求和文本长度有用。

- (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];
}

答案 3 :(得分:1)

注意:这是基于@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
}

答案 4 :(得分:1)

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

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

    override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    
  • 确保单元格中的每个元素都有一个top / bottom / left / right =约束(不是> =,< =,或者alignX或alignY - 它必须是=)。您可以将此设置为低优先级约束并提供更高优先级的更好约束,但您必须为其提供一个确切的起始值来确定单元格的大小。

答案 5 :(得分:1)

以下是Swift 3的一个简单示例。我们在Storyboard中设置UITableViewController类型分组,内容类型为静态单元格。其tableView包含一个UITableViewCell。单元格包含一个UILabel,其中有多行设置为 0 ,还有一些非常长的文本要显示。该标签还有四个自动布局约束,其superView顶部底部前导尾随)。

enter image description here

现在,您可以选择以下四个代码段中的一个,以便让静态单元格根据其内容自动调整大小。

#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
    }

}

以前的所有四个代码段将显示以下内容:

答案 6 :(得分:0)

我认为我需要告诉单元格使用

之类的东西重绘
[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.
  }

答案 7 :(得分:0)

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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 2)  //Dynamic Height
    {
        return UITableViewAutomaticDimension;
    }
    else 
    {
        return 50;  // Static Height
    }
}