Ios 什么是NSLayoutConstraint“;UIView封装布局高度“;我该如何强制它干净地重新计算呢?
我有一个在iOS 8下运行的Ios 什么是NSLayoutConstraint“;UIView封装布局高度“;我该如何强制它干净地重新计算呢?,ios,uitableview,cocoa-touch,autolayout,ios-autolayout,Ios,Uitableview,Cocoa Touch,Autolayout,Ios Autolayout,我有一个在iOS 8下运行的UITableView,我使用的是故事板中约束条件下的自动单元格高度 我的一个单元格包含一个UITextView,我需要它根据用户输入收缩和展开-点击可收缩/展开文本 为此,我将向文本视图添加运行时约束,并根据用户事件更改约束上的常量: -(void)collapse:(BOOL)collapse; { _collapsed = collapse; if(collapse) [_collapsedtextHeightConstrai
UITableView
,我使用的是故事板中约束条件下的自动单元格高度
我的一个单元格包含一个UITextView
,我需要它根据用户输入收缩和展开-点击可收缩/展开文本
为此,我将向文本视图添加运行时约束,并根据用户事件更改约束上的常量:
-(void)collapse:(BOOL)collapse; {
_collapsed = collapse;
if(collapse)
[_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
else
[_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];
[self setNeedsUpdateConstraints];
}
执行此操作时,我将其包装在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];
当我执行此操作时,我的单元格确实会展开(并在进行此操作时设置动画),但我会收到一条约束警告:
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)]>
2014-07-31 13:29:51.792 OneFlateEarth[5505:730175]无法同时满足约束条件。
可能下面列表中至少有一个约束是您不想要的。试着这样做:(1)看看每个约束,试着找出你不期望的约束;(2) 找到添加了不需要的约束的代码,然后修复它。(注意:如果您看到不理解的NSAutoresizingMaskLayoutConstraints,请参阅UIView属性TranslatesAutoResizingMaskToConstraints的文档)
(
"",
"",
"",
""
)
将尝试通过打破约束进行恢复
388是我计算的高度,UITextView
上的其他约束是我从Xcode/IB得到的
最后一个问题困扰着我-我猜UIView-enclosed-Layout-Height
是第一次渲染时计算出的单元格高度-(我将UITextView
高度设置为>=70.0),但是这个派生的约束会推翻更新的用户cnstraint,这似乎是不对的
更糟糕的是,尽管布局代码说它试图打破我的高度限制,但事实并非如此——它继续重新计算单元格高度,并按照我的意愿绘制所有内容
那么,什么是
NSLayoutConstraint
UIView封装布局高度(我猜它是自动调整单元格大小的计算高度)以及我应该如何强制它干净地重新计算?与其通知表视图更新其约束,不如尝试重新加载单元格:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
ui视图封装布局高度
可能是在初始加载期间,基于单元格当时的约束,为单元格计算的表格视图高度。尝试将\u collapsedtextHeightConstraint
的优先级降低到999。这样,系统提供的ui视图封装布局高度约束始终优先
它基于您在-tableView:heightforrowatinexpath:
中返回的内容。确保返回正确的值和您自己的约束,并且生成的约束应该相同。您自己的约束的较低优先级仅在折叠/展开动画运行时临时需要,以防止冲突
另外:虽然系统提供的约束是否正确可能有争议,但与框架抗争没有任何意义。只需接受系统约束优先。如果您认为系统约束错误,请确保从代理返回正确的行高。调整文本视图大小以适应其内容,并将高度约束常量更新为结果高度,修复了我的UIView封装布局高度
约束冲突,例如:
[self.textView sizeToFit];
self.textViewHeightConstraint.constant = self.textView.frame.size.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
}
我可以通过在约束中的一个值上指定一个值来得到警告,警告消息说它必须破坏(下面的“将尝试通过破坏约束来恢复”
)。似乎只要我将优先级设置为大于49
,警告就会消失
对我来说,这意味着改变我的约束,警告说它试图打破:
@“V:|[contentLabel]-[quoteelab]|”
致:
@“V:|-0@500-[contentLabel]-[QuoteLabel]|“
事实上,我可以为该约束的任何元素添加一个优先级,它将起作用。哪一个似乎无关紧要。我的单元格最终达到了正确的高度,并且没有显示警告。罗杰,举个例子,试着在388
高度值约束之后添加@500
(例如388@500
)
我不完全确定为什么会这样,但我做了一些调查。在中,NSLayoutPriorityFittingSizeCompression
优先级似乎为50
。该优先级的文档说明:
向视图发送fittingSize消息时,显示的最小尺寸
足够大,以便计算视图的内容。这是
视图希望在中尽可能小的优先级级别
这个计算。很低。这通常不适合于
严格按照此优先级进行约束。你想更高还是更高
更低
参考的fittingSize
消息的内容如下:
满足其约束的视图的最小大小。
(只读)
AppKit将此属性设置为视图可用的最佳大小,
考虑到所有约束,它及其子视图保持并
满足使视图尽可能小的首选项。这个
此属性中的大小值从不为负值
我还没有挖掘出更多的东西,但这似乎是有道理的,这与问题所在有关。我有一个
"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"
myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works
myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem
top (10@1000)
cell
bottom (0@1000)
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[title]-|" options:0 metrics:nil views:views];
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6@999-[title]-6@999-|" options:0 metrics:nil views:views];
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[title]-6-|" options:0 metrics:nil views:views];
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
let companyNameTopConstraint = companyNameLabel.topAnchor.constraint(equalTo: companyImageView.bottomAnchor, constant: 15)
companyNameTopConstraint.priority = .defaultHigh
NSLayoutConstraint.activate([
companyNameTopConstraint,
the rest of your constraints here
])
2020-08-06 21:33:20.947369+0530 DemoNestedTableView[4181:384993] [LayoutConstraints] 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.
(
"<NSLayoutConstraint:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326 (active)>",
"<NSLayoutConstraint:0x600000a3ae40 V:|-(0)-[UICollectionView:0x7fde0780c200] (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
"<NSLayoutConstraint:0x600000a3af30 V:[UICollectionView:0x7fde0780c200]-(0)-| (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
"<NSLayoutConstraint:0x600000a2a4e0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fde05e0cb10.height == 326.5 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326 (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
self.tableView.separatorStyle = .none