我正在学习/试验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/