如何在 UITableViewController 中设置静态单元格的自动高度?

Posted

技术标签:

【中文标题】如何在 UITableViewController 中设置静态单元格的自动高度?【英文标题】:How to set automatic height of static cell in UITableViewController? 【发布时间】:2015-06-04 18:32:13 【问题描述】:

我正在使用 IB 和故事板,我定义了 UITableViewController。我在那里定义了三个 static 单元格。前两个应该具有给定的高度,但最后一个应该自动填充剩余空间(锚定到视图底部)。我怎样才能做到这一点?我可以对单元格内部的控件使用自动布局,但单元格本身显示为灰色。

最好的解决方案是从 IB 执行此操作,但也欢迎程序化解决方案。

编辑:

这是它在我的故事板中的外观(颜色用于可视化单独的控件,每个控件都有所需的约束):

启动后: 请注意,文本视图在屏幕底部下方结束。

我忘了说我的目标是 ios 7.0+。

【问题讨论】:

【参考方案1】:

您实际上可以将UITableViewAutomaticDimension 与静态单元格一起使用。按照惯例设计静态单元格,并通过添加手动将单元格设置为动态高度

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 240 // Something reasonable to help ios render your cells

现在覆盖 heightForRow 委托

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

我注意到使用此技术的唯一其他警告是您必须使用NSAutolayout 来创建对底部容器(UITableViewCell 的容器)的约束。因此,假设您在单元格的 contentView 中有一个容器,该容器将具有动态高度,要使其正确呈现,您需要创建一个底部空间约束。

如果您有一些具有固定高度的静态单元格,我建议通过在tableView:heightForRowAtIndexPath:indexPath 中打开行来返回该大小

【讨论】:

使用自动布局不是一个警告,它是一个功能! 非常适合我。我还实现了tableView.reloadData(),以便在我更改此静态单元格中的内容时重新计算单元格高度。 @SwiftArchitect 非常正确,我想我的意思是“不要忘记”你的底部约束 设置rowHeightestimatedRowHeight后,为什么需要实现委托方法heightForRowAtIndexPath @MrRogers 我猜是因为您可以为某些单元格设置自定义高度,并且默认实现会覆盖委托方法以使用这些高度【参考方案2】:

一定要覆盖 heightForRowAtIndexPath!否则,根据我的经验,它将无法正确显示

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

    return UITableViewAutomaticDimension
 

【讨论】:

【参考方案3】:

好的,试试这个

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

    if indexPath.row == 0  
        return firstRowHeight
    
    else if indexPath.row == 1  
        return secondRowHeight 
    
    else  
        return tableView.frame.size.height - firstRowHeight - secondRowHeight 
    

唯一可能有问题的是这个方法要在视图设置tableView高度之前运行

【讨论】:

这是目前最好的选择。但是,我需要为第三行再减去 63 个像素,也许是为了导航栏? 所以63(好吧,实际上是64)是导航栏的高度+状态栏的高度。我有点奇怪tableView height 确实包含它们…… 通常你不应该减去导航。酒吧高度。使用视图调试查看实际的tableView高度是多少。【参考方案4】:

我在一篇博客文章中介绍了这一点,它使用静态表格视图并使用自动布局设置单元格高度。单元格都在界面生成器中定义。

您必须在代码中启用自动单元格高度,但这只是几行代码。

我展示了一切,包括 IB 和代码。

看看

http://www.oliverfoggin.com/using-a-static-uitableview-as-a-layout-device/

【讨论】:

这是我设置约束并返回 UITableViewAutomaticDimension 的高度时的样子:link(请参阅更新的问题以供参考)。我也忘了提到我的目标是 iOS 7.0+。【参考方案5】:

如果整个 tableview 单元格高度是动态的,那么你可以试试这个

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 240

或者表格视图需要一些固定高度的单元格和一些动态高度的单元格,您可以查看答案 Dynamic & static tableview cell height

希望对你有帮助。

【讨论】:

在静态单元格中,这不起作用。但是tableView:heightForRowAtIndexPath: 的代理运行良好,因为UITableViewController 有自己的实现,关于如何获取单元格的高度。【参考方案6】:

不确定来自 IB 和使用自动布局

但是以编程方式使用,

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

使用此方法,您可以检查 indexpath.row。并使用它返回不同的高度。

【讨论】:

我当然知道那个方法,但问题是我应该为第三行返回什么......【参考方案7】:

Ryan Romanchuk 的回答很棒。我有一个技巧可以帮助像我这样的初学者。

由于这是一个静态单元格案例,您可能倾向于对每个动态字段使用IBOutlet。在tableView 加载循环之外的UILabel 中设置值将不会考虑新的高度。

要允许动态高度起作用,您可以在覆盖的cellForRowAtIndexPath 委托中分配值,以便自动布局可以获取新高度。如需更新字段,请致电tableView.reloadData()

【讨论】:

【参考方案8】:

对于静态(非数据驱动)高度,您只需将单元格出列一次并存储高度:

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

    static NSNumber *height;
    if (!height) 
        UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCustomCell"];
        height = @(cell.bounds.size.height);
    
    return [height floatValue];

【讨论】:

我不明白这对我有什么帮助……

以上是关于如何在 UITableViewController 中设置静态单元格的自动高度?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UITableViewController 之上添加 UIView [关闭]

如何将 UITableViewController 创建为可重用模块?

如何将 uitoolbar 添加到 uitableviewcontroller?

如何在当前 UITableViewController 上方添加一个 UIView

Swift:如何在 UITableViewController(包含 UICollectionView)中使用“didSelectItemAtIndexPath”?

使用 UITableViewController 时如何让 pickerView 粘在底部?