首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UITableView灵活/动态heightForRowAtIndexPath

UITableView灵活/动态heightForRowAtIndexPath
EN

Stack Overflow用户
提问于 2010-02-06 20:11:15
回答 7查看 26.3K关注 0票数 60

案例

通常,您将使用cellForRowAtIndexPath委托方法来设置计算单元。为单元格设置的信息对于单元格的绘制方式和大小很重要。

不幸的是,heightForRowAtIndexPath委托方法在cellForRowAtIndexPath委托方法之前被调用,因此我们不能简单地告诉该委托返回单元格的高度,因为此时高度将为零。

因此,在表格中绘制单元格之前,我们需要计算大小。幸运的是,有一个属于NSString类的方法sizeWithFont可以做到这一点。但是有一个问题,为了动态地计算正确的大小,它需要知道单元格中的元素将如何呈现。我将在一个示例中说明这一点:

假设有一个UITableViewCell,它包含一个名为textLabel的标签。在cellForRowAtIndexPath委托方法中,我们放置了textLabel.numberOfLines = 0,它基本上告诉标签,它可以有任意多的行来表示特定宽度的文本。如果我们给textLabel的文本比最初给textLabel的宽度大,就会出现问题。第二行将出现,但单元格的高度不会自动调整,因此我们得到了一个混乱的表视图。

正如前面所说的,我们可以使用sizeWithFont来计算高度,但是它需要知道使用了哪个字体,宽度是多少等等。如果出于简单的原因,我们只关心宽度,我们可以硬编码宽度大约是320.0 (不考虑填充)。但是,如果我们使用UITableViewStyleGrouped而不是纯文本,会发生什么呢?宽度将在300.0左右,单元格将再次变得混乱。或者如果我们从纵向到横向交换会发生什么,我们有更多的空间,但它不会被使用,因为我们硬编码了300.0。

在这种情况下,有时你必须问自己一个问题,你可以在多大程度上避免硬编码。

我自己的想法

您可以调用属于UITableView类的cellForRowAtIndexPath方法来获取特定部分和行的单元格。我读了几篇文章,说你不想这么做,但我真的不太明白。是的,我同意它已经分配了单元格,但heightForRowAtIndexPath委托方法只为将可见的单元格调用,因此无论如何都会分配该单元格。如果您正确使用dequeueReusableCellWithIdentifier,则不会在cellForRowAtIndexPath方法中再次分配单元格,而是使用一个指针,并且仅调整属性。那有什么问题呢?

请注意,单元格不是在cellForRowAtIndexPath委托方法中绘制的,当表格视图单元格变为可见时,脚本将在UITableVieCell上调用setNeedDisplay方法,从而触发drawRect方法来绘制单元格。因此,直接调用cellForRowAtIndexPath委托不会降低性能,因为它需要绘制两次。

好的,通过在heightForRowAtIndexPath委托方法中调用cellForRowAtIndexPath委托方法,我们获得了确定单元格大小所需的所有信息。

也许你可以创建自己的sizeForCell方法来遍历所有选项,如果单元格是Value1样式的,或者是Value2样式的,等等。

结论/问题

这只是我在脑海中描述的一个理论,我想知道我写的是不是正确的。或者,也许有另一种方法可以完成同样的事情。请注意,我希望能够尽可能灵活地做事情。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-07-13 00:02:58

是的,我同意它已经分配了单元格,但heightForRowAtIndexPath委托方法只为将可见的单元格调用,因此无论如何都会分配该单元格。

这是不正确的。表视图需要为表视图中的所有行调用heightForRowAtIndexPath (如果已实现),而不仅仅是当前显示的那些行。原因是它需要计算出它的总高度才能显示正确的滚动指示器。

票数 26
EN

Stack Overflow用户

发布于 2010-02-07 01:41:21

我过去常常通过以下方式做到这一点:

  1. 创建集合对象(大小信息的数组(字典、行高的NSNumber等)基于将用于表视图的集合对象。
  2. 这是在我们处理来自本地或远程源的数据时完成的。
  3. 我在创建此集合对象时预先确定了将使用的字体的类型和大小。您甚至可以存储UIFont对象或用于表示内容的任何自定义对象。
  4. 每次我实现UITableViewDataSource或UITableViewDelegate协议以确定UITableViewCell实例及其子视图等的大小时,都将使用这些集合对象。

通过这种方式,您可以避免仅仅为了获取其内容的各种大小属性而对UITableViewCell进行子类化。

不要使用绝对值来初始化帧。使用基于当前方向和边界的相对值。

如果我们将它旋转到任何方向,只需在运行时调整大小即可。确保autoresizingMask设置正确。

您只需要高度,而不需要UITableViewCell中所有不必要的东西来确定行的高度。您甚至可能不需要宽度,因为正如我所说的,宽度值应该相对于视图边界。

票数 8
EN

Stack Overflow用户

发布于 2012-08-08 11:51:06

下面是我解决这个问题的方法

  1. 在此解决方案中,我假设只有一个标签具有“动态”高度
  2. 我还假设,如果我们使标签自动调整大小以随着单元格的增长而拉伸高度,则只需要单元格的高度来更改
  3. 我假设标签的位置和上方的间距具有适当的间距,并将其置于下方
  4. 我们不想在每次更改标签的字体或位置时都更改代码

<

  1. >G29>

如何更新高度:

代码语言:javascript
复制
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    // We want the UIFont to be the same as what is in the nib,
    //  but we dont want to call tableView dequeue a bunch because its slow. 
    //  If we make the font static and only load it once we can reuse it every
    //  time we get into this method
    static UIFont* dynamicTextFont;
    static CGRect textFrame;
    static CGFloat extraHeight;
    if( !dynamicTextFont ) {
        DetailCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
        dynamicTextFont = cell.resizeLabel.font;
        CGRect cellFrame = cell.frame;
        textFrame = cell.resizeLabel.frame;
        extraHeight = cellFrame.size.height-textFrame.size.height; // The space above and below the growing field
    }
    NSString* text = .... // Get this from the some object using indexPath 

    CGSize  size = [text sizeWithFont:dynamicTextFont constrainedToSize:CGSizeMake(textFrame.size.width, 200000.f) lineBreakMode:UILineBreakModeWordWrap];

    return size.height+extraHeight;
}

问题:

  • 如果您不使用原型单元格,则需要检查该单元格是否为nil并对其进行初始化
  • 您的nib /情节提要必须具有UILabel自动调整大小并将多行设置为0
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2213024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档