Isu*_*uru 60 uitableview ios autolayout swift ios8
在我正在创建的iOS 8应用程序中,我有一个tableview,我需要它们自我调整大小.我使用自动布局实现它,它的工作原理.几乎.这是它现在的样子.
单元格内有3个标签.主要标签有lorem ipsum文本.带有数字串的字幕(这是两个单独的标签.可能会因为颜色相同而混淆.)然后第三个标签带有小黑色文字.
第一个标签正确调整大小没有问题,第二个标签相应地上下移动.但问题在于第三个小标签.正如您所看到的,它没有调整自身大小以适应所有文本.
现在发生了一件奇怪的事情.我把它转向风景,这就是它.
由于存在空间,标签正在显示其应有的整个文本.精细.然后我把它变回肖像.
现在,小标签已经调整大小以适应其所有文本,但它溢出了单元格边界.我试着把细胞做大,但是没用.由于这是自我调整细胞,我不认为这是正确的方法.
我没有收到任何错误,甚至没有警告我的汽车布局限制.
我在方法中设置了这两行代码viewDidLoad()
.
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
Run Code Online (Sandbox Code Playgroud)
谁能告诉我这里可能做错了什么?
由于仅仅通过查看图像很难回答,而且我没有更多的代码可以在上面的代码段旁边发布,我上传了一个可运行的Xcode项目,在这里展示了这个问题.(有2个自定义单元格.基本上它是同一个单元格,只是高度在第二个单元格中增加.)
我一直在摆弄汽车布局限制,但我似乎无法让这个工作.任何帮助,将不胜感激.
谢谢.
更新:
在本教程的帮助下,我发现了一些有用的指针.根据它,每个子视图应该具有固定其所有边的约束,并且应该存在从上到下的约束,这有助于自动布局以计算单元的高度.在我的原始帖子中,我在每个标签之间有垂直空间,所以我认为这是自动布局无法计算正确高度的原因.
所以我做了一些改变.
现在这是另一个奇怪的部分.当我第一次运行它时,底部标签裁剪问题仍然存在.
但是,如果我将设备旋转到横向并将其转回肖像,则所有单元格都会正确调整大小以适合两个标签!
仍然无法弄清楚为什么一开始不会发生这种情况.更新的Xcode项目在这里.
smi*_*org 83
这里的问题是多行标签的preferredMaxLayoutWidth
属性.这是告诉标签应该自动换行的属性.必须正确设置才能使每个标签intrinsicContentSize
具有正确的高度,这最终将使用自动布局来确定单元格的高度.
Xcode 6 Interface Builder引入了一个新选项,可将此属性设置为Automatic.不幸的是,有一些严重的错误(从Xcode 6.2/iOS 8.2开始),当从笔尖或故事板加载单元格时,没有正确/自动设置.
为了解决这个bug,我们需要让preferredMaxLayoutWidth
set在表格视图中显示时完全等于标签的最终宽度.实际上,我们希望在返回单元格之前执行以下操作tableView:cellForRowAtIndexPath:
:
cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)
Run Code Online (Sandbox Code Playgroud)
单独添加此代码不起作用的原因是因为当执行这3行代码时tableView:cellForRowAtIndexPath:
,我们使用每个标签的宽度来设置preferredMaxLayoutWidth
- 但是,如果您在此时检查标签的宽度时间,标签宽度完全不同于一旦显示单元格并且其子视图已经布局,它将最终变为什么.
我们如何在此时使标签宽度准确,以便它们反映最终宽度?这是使它们聚集在一起的代码:
// Inside of tableView:cellForRowAtIndexPath:, after dequeueing the cell
cell.bounds = CGRect(x: 0, y: 0, width: CGRectGetWidth(tableView.bounds), height: 99999)
cell.contentView.bounds = cell.bounds
cell.layoutIfNeeded()
cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)
Run Code Online (Sandbox Code Playgroud)
好的,那我们在这做什么呢?好吧,您会注意到添加了3行新代码.首先,我们需要设置此表格视图单元格的宽度,使其与表格视图的实际宽度相匹配(这假定表格视图已经布局并具有其最终宽度,应该是这种情况).我们实际上只是尽早使单元格宽度正确,因为表格视图最终会这样做.
您还会注意到我们正在使用99999
高度.那是什么意思?对于此处详细讨论的问题,这是一个简单的解决方法,其中如果您的约束需要比单元格的contentView的当前高度更多的垂直空间,则会得到一个约束异常,实际上并不表示任何实际问题.单元格或其任何子视图的高度此时并不重要,因为我们只关心获取每个标签的最终宽度.
接下来,我们通过将contentView的边界设置为等于单元格的边界,确保单元格的contentView与我们刚刚分配给单元格本身的大小相同.这是必要的,因为您创建的所有自动布局约束都与contentView相关,因此contentView必须是正确的大小才能正确解决.手动设置单元格的大小不会自动调整contentView的大小以匹配.
最后,我们强制在单元格上进行布局传递,这将使自动布局引擎解决您的约束并更新所有子视图的帧.由于单元格和contentView现在具有相同的宽度,它们将在运行时在表格视图中,标签宽度也将是正确的,这意味着preferredMaxLayoutWidth
每个标签的设置将是准确的,并将导致标签在正确的时间换行,这当然意味着当在表格视图中使用单元格时,标签的高度将被正确设置!
这绝对是UIKit中的Apple漏洞,我们现在必须解决这个问题(所以请向Apple 提交bug报告,以便他们优先考虑修复!).
最后要注意的是:如果表视图单元格的contentView
宽度没有扩展到表视图的整个宽度,则此解决方法将遇到麻烦,例如,当右侧显示节索引时.在这种情况下,您需要确保在设置单元格的宽度时手动考虑这一点 - 您可能需要对这些值进行硬编码,例如:
let cellWidth = CGRectGetWidth(tableView.bounds) - kTableViewSectionIndexWidth
cell.bounds = CGRect(x: 0, y: 0, width: cellWidth, height: 99999)
Run Code Online (Sandbox Code Playgroud)
小智 50
我遇到了和你一样的问题,我找到了解决它的简单解决方案.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// dequeue cell...
// do autolayout staffs...or if the autolayout rule has been set in xib, do nothing
[cell layoutIfNeeded];
return cell;
}
Run Code Online (Sandbox Code Playgroud)
自我调整很好.在我的代码中,我在垂直方向放置了两个标签,它们都是动态高度.正确设置单元格的高度以包含两个标签.
假设你的约束没有任何其他人提出的错误,这个问题似乎源于使用UILabel,它允许多行与UITableViewCellAccessory结合使用.当iOS布置单元格并确定高度时,它不会考虑由于此附件而发生的宽度偏移变化,并且您会在不期望的位置进行截断.
假设您希望UILabel扩展内容视图的整个宽度,我编写了一个方法来修复所有字体大小
-(void)fixWidth:(UILabel *)label forCell:(UITableViewCell *)cell {
float offset = 0;
switch ([cell accessoryType]) {
case UITableViewCellAccessoryCheckmark:
offset = 39.0;
break;
case UITableViewCellAccessoryDetailButton:
offset = 47.0;
break;
case UITableViewCellAccessoryDetailDisclosureButton:
offset = 67.0;
break;
case UITableViewCellAccessoryDisclosureIndicator:
offset = 33.0;
break;
case UITableViewCellAccessoryNone:
offset = 0;
break;
}
[label setPreferredMaxLayoutWidth:CGRectGetWidth([[self tableView]frame]) - offset - 8];
}
Run Code Online (Sandbox Code Playgroud)
只需将它放在你的cellForRowAtIndexPath中
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
#Setup the cell
...
// Fix layout with accessory view
[self fixWidth:[cell label] forCell:cell];
return cell;
}
Run Code Online (Sandbox Code Playgroud)
对任何有多行的标签进行适当调整宽度,然后重新计算适当的高度.这也适用于动态字体大小.
就像smileyborg提到的那样,如果你没有使用contentView的全宽,你可以引用约束并从宽度中减去它们.
编辑:我之前在单元格上运行'layoutIfNeeded',但这会产生性能问题,而且似乎无论如何都不需要.删除它并没有给我带来任何问题.
归档时间: |
|
查看次数: |
40161 次 |
最近记录: |