systemLayoutSizeFittingSize

systemLayoutSizeFittingSize

我正在学习/试验autolayout和UITableViewCell。几天前我问了另一个问题,回答了我自己的问题,但我仍在使用相同的约束/代码。有关完整代码,请参见此处:AutoLayout multiline UILabel cutting off some text

为了简化它在heightForRowAtIndexPath中的使用,我使用一个自定义UITableViewCell的实例来计算该行所需的高度。这在纵向模式下效果很好,但是当我切换到横向模式时,systemLayoutSizeFittingSize返回的单元格高度与纵向模式相同。我已经打印出contentView和标签的框架,似乎没有任何更新。

这样做的结果是约束迫使标签增长而留下大量空白。标签以正确的宽度显示,按照我期望的方式横向放置标签。如果我对单元格的高度进行硬编码,它可以完美地工作。

看起来像这样:

硬编码后(我希望它看起来像):

更糟糕的是,在iPad上运行时甚至在人像模式下,我得到的结果都是相同的,这意味着我得到了iPhone的尺寸。从我所看到的,就好像systemLayoutSizeFittingSize对此没有方向或设备的概念。

我试过伪造该单元格应该是的frame,尝试旋转该单元格,调用layoutSubviews,在方向改变时重新加载tableView,似乎没有任何影响。

我错过了一些基本的东西吗?

最佳答案

@rdelmar有正确的方法。在对contentView调用systemLayoutSizeFittingSize之前,您肯定需要重置每个标签上的preferredMaxLayoutWidth。正如他所演示的,我还将UILabel子类与layoutSubviews方法一起使用。

这样的自动布局方法的主要缺点是开销。对于每个将要显示的单元格,我们实际上有效地运行了三遍自动布局:一次为systemLayoutSizeFittingSize准备大小调整单元格(为其设置大小并在每个子标签上设置preferredMaxLayoutWidth),再次调用systemLayoutSizeFittingSize,并在实际单元格上再次返回来自cellForRowAtIndexPath。

为什么我们需要/想要第一次自动布局?没有它,我们不知道将子标签的preferredMaxLayoutWidth值设置为什么宽度。我们可以像@rdelmars示例中那样对值进行硬编码(这很好),但是如果您更改单元格布局或要处理的单元格类型很多,则它会更脆弱。

如果主要问题是重新确定方向变化,则可以优化以下代码,以使每个方向变化仅运行一次布局遍。

这是我使用的模式,不需要在 View Controller 中操作单元格控件。它的封装性更强,但价格可能更高。

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // assumes all cells are of the same type!
    static UITableViewCell* cell;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        cell = [tableView dequeueReusableCellWithIdentifier: @"label_cell"];
    });

    // size the cell for the current orientation.  assume's we're full screen width:
    cell.frame = CGRectMake(0, 0, tableView.bounds.size.width, cell.frame.size.height );

    // perform a cell layout - this runs autolayout and also updates any preferredMaxLayoutWidths via layoutSubviews in our subclassed UILabels
    [cell layoutIfNeeded];

    // finally calculate the required height:
    CGSize s = [cell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];

    return s.height + 1; // +1 because the contentView is 1pt shorter than the cell itself when there's a separator.  If no separator you shouldn't need +1
}

随着:
@interface TSLabel : UILabel
@end

@implementation TSLabel

- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
    [super layoutSubviews];
}

@end

关于ios - 横向和iPad上的AutoLayout uitableviewcell基于人像iPhone计算高度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23496547/

10-09 09:37