Rog*_*Rog 243 cocoa-touch uitableview ios autolayout ios-autolayout
我UITableView
在iOS 8下运行,并且我在故事板中使用来自约束的自动单元格高度.
我的一个单元格包含一个UITextView
,我需要它根据用户输入收缩和扩展 - 点击缩小/扩展文本.
我这样做是通过向文本视图添加运行时约束并更改约束上的常量以响应用户事件:
-(void)collapse:(BOOL)collapse; {
_collapsed = collapse;
if(collapse)
[_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
else
[_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];
[self setNeedsUpdateConstraints];
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我将其包装在tableView
更新中并致电[tableView setNeedsUpdateConstraints]
:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView setNeedsUpdateConstraints];
// I have also tried
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.
[tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我的单元格确实扩展(并在进行动画时动画)但是我得到一个约束警告:
2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",
"<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-| (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'] (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>
Run Code Online (Sandbox Code Playgroud)
388是我计算的高度,其他约束UITextView
是我的Xcode/IB.
最后一个困扰我 - 我猜UIView-Encapsulated-Layout-Height
这是第一次渲染时单元格的计算高度 - (我将我的UITextView
高度设置为> = 70.0)但是这个派生约束然后否定了更新了用户cnstraint.
更糟糕的是,虽然布局代码表示它试图打破我的高度限制,但它没有 - 它继续重新计算单元格高度,所有内容都按照我的意愿绘制.
那么,是什么NSLayoutConstraint
UIView-Encapsulated-Layout-Height
(我猜它是自动细胞大小的计算高度),我应该如何强制它干净地重新计算?
Ort*_*ntz 287
尝试将您的优先级降低_collapsedtextHeightConstraint
到999.这样系统提供的UIView-Encapsulated-Layout-Height
约束始终优先.
它取决于你的回归 -tableView:heightForRowAtIndexPath:
.确保返回正确的值和您自己的约束,生成的约束应该相同.只有暂时需要您自己的约束的较低优先级,以防止崩溃/扩展动画在飞行中时发生冲突.
Gol*_*umb 66
我有一个类似的场景:一个带有一个行单元格的表视图,其中有几行UILabel对象.我正在使用iOS 8和自动布局.
当我旋转时,我得到了错误的系统计算行高(43.5远小于实际高度).看起来像:
"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"
Run Code Online (Sandbox Code Playgroud)
这不仅仅是一个警告.我的表格视图单元格的布局很糟糕 - 所有文本都重叠在一个文本行上.
令我惊讶的是,以下行神奇地"修复"了我的问题(自动布局没有抱怨,我得到了我在屏幕上的预期):
myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works
Run Code Online (Sandbox Code Playgroud)
有或没有这条线:
myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem
Run Code Online (Sandbox Code Playgroud)
小智 35
99.9% 的情况下,在使用自定义单元格或标题时,所有冲突都UITableViews
发生在第一次加载表格时。加载后,您通常不会再次看到冲突。
发生这种情况是因为大多数开发人员通常使用某种固定高度或锚点约束来布局单元格/标题中的元素。发生冲突是因为当第UITableView
一次加载/布局时,它将其单元格的高度设置为 0。这显然与您自己的约束冲突。要解决此问题,只需将任何固定高度约束设置为较低优先级 ( .defaultHigh
)。仔细阅读控制台消息,看看布局系统决定打破哪个约束。通常这是需要改变其优先级的那个。您可以像这样更改优先级:
let companyNameTopConstraint = companyNameLabel.topAnchor.constraint(equalTo: companyImageView.bottomAnchor, constant: 15)
companyNameTopConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([
companyNameTopConstraint,
the rest of your constraints here
])
Run Code Online (Sandbox Code Playgroud)
Jef*_*wen 31
通过在约束中指定其中一个值的优先级,警告消息说它必须中断(下面"Will attempt to recover by breaking constraint"
),我能够得到警告消失.似乎只要我将优先级设置为大于的值49
,警告就会消失.
对我而言,这意味着改变我的约束警告称它试图破坏:
@"V:|[contentLabel]-[quoteeLabel]|"
至:
@"V:|-0@500-[contentLabel]-[quoteeLabel]|"
事实上,我可以为该约束的任何元素添加优先级,它将起作用.似乎哪个不重要.我的细胞最终达到了正确的高度,并且没有显示警告.Roger,例如,@500
在388
高度值约束之后尝试添加(例如388@500
).
我不完全确定为什么会这样,但我做了一些调查.在NSLayoutPriority枚举中,NSLayoutPriorityFittingSizeCompression
优先级似乎是50
.该优先级的文档说:
将fittingSize消息发送到视图时,将计算足够大的视图内容的最小大小.这是视图希望在该计算中尽可能小的优先级.它很低.通常不恰当地以此优先级进行约束.你想要更高或更低.
引用消息的文档fittingSize
如下:
满足其所拥有约束的视图的最小大小.(只读)
AppKit将此属性设置为视图可用的最佳大小,考虑它及其子视图所具有的所有约束并满足偏好以使视图尽可能小.此属性中的大小值永远不会为负数.
我没有挖过这个,但似乎有意义的是这与问题所在.
Cli*_*rum 11
通过删除cell.layoutIfNeeded()
我tableView
的cellForRowAt
方法中的虚假,我能够解决这个错误.
不要通知表视图更新其约束,请尝试重新加载单元格:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)
UIView-Encapsulated-Layout-Height
可能是表格视图在初始加载期间为单元格计算的高度,具体取决于当时单元格的约束.
另一种可能性
如果使用自动布局来计算单元格高度(contentView的高度,大部分时间如下所示),并且如果您有uitableview分隔符,则需要添加分隔符高度,以便返回单元格高度.一旦获得正确的高度,就不会有自动布局警告.
- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
[sizingCell setNeedsLayout];
[sizingCell layoutIfNeeded];
CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height; // should + 1 here if my uitableviewseparatorstyle is not none
}
Run Code Online (Sandbox Code Playgroud)
正如杰西在有问题的评论中提到的,这对我有用:
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
Run Code Online (Sandbox Code Playgroud)
仅供参考,此问题在 iOS 10 中不会发生。
使用 UITableViewAutomaticDimension 并更改单元格内视图的高度约束时出现此错误。
我终于发现这是由于约束常量值没有被四舍五入到最接近的整数。
let neededHeight = width / ratio // This is a CGFloat like 133.2353
constraintPictureHeight.constant = neededHeight // Causes constraint error
constraintPictureHeight.constant = ceil(neededHeight) // All good!
Run Code Online (Sandbox Code Playgroud)