UICollectionViewCell 自动布局

Posted

技术标签:

【中文标题】UICollectionViewCell 自动布局【英文标题】:UICollectionViewCell Auto Layout 【发布时间】:2014-10-25 17:29:02 【问题描述】:

我在故事板中创建了一个简单的自定义 UICollectionViewCell,我也以编程方式完成了此操作,结果相同。

它有一个单数UIImageView和两个UILabels,像这样:

          <--UIIMAGEVIEW-->          <--UILABEL-------->
|-(10px)- |               | -(10px)-                     -(10px)-|
          <--------------->          <--UILABEL-------->

图像位于左侧,然后在其右侧是上下两个标签。

每个都以 10 个像素的间隙间隔开,并且都以单元格 Y 轴为中心。然后标签有一个常数来从中心偏移它们(向上和向下)。

图像的高度和宽度固定为 44px,标签的高度固定为 20px(宽度灵活)。

这些约束按预期工作并且永远不会破坏应用程序,但它们总是在下面吐出这个烦人的控制台日志信息,因为它们显然正在破坏。

如果我将此行添加到我的 UICollectionViewCell 子类中,则约束不再中断并显示控制台错误,但它们在屏幕上完全中断。

[self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];

有什么线索吗?这似乎太不合逻辑了!

这是控制台错误代码:

2014-10-25 18:28:14.273 Air Plan[1579:580797] 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:0x17009edc0 H:[UIImageView:0x1701f7d00(44)]>",
    "<NSLayoutConstraint:0x17009f130 H:|-(10)-[UIImageView:0x1701f7d00]   (Names: '|':UIView:0x170183810 )>",
    "<NSLayoutConstraint:0x17009f270 H:[UIImageView:0x1701f7d00]-(10)-[UILabel:0x155e59970'detailLbl']>",
    "<NSLayoutConstraint:0x17009f310 H:[UILabel:0x155e59970'detailLbl']-(10)-|   (Names: '|':UIView:0x170183810 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x17409eff0 h=--& v=--& H:[UIView:0x170183810(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17009edc0 H:[UIImageView:0x1701f7d00(44)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-10-25 18:28:14.276 Air Plan[1579:580797] 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:0x17009fcc0 H:[UIImageView:0x1701fa800(44)]>",
    "<NSLayoutConstraint:0x17009ff40 H:|-(10)-[UIImageView:0x1701fa800]   (Names: '|':UIView:0x170180a90 )>",
    "<NSLayoutConstraint:0x1702800a0 H:[UIImageView:0x1701fa800]-(10)-[UILabel:0x155e5b440'detailLbl']>",
    "<NSLayoutConstraint:0x170280140 H:[UILabel:0x155e5b440'detailLbl']-(10)-|   (Names: '|':UIView:0x170180a90 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x17409ea00 h=--& v=--& H:[UIView:0x170180a90(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17009fcc0 H:[UIImageView:0x1701fa800(44)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-10-25 18:28:14.278 Air Plan[1579:580797] 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:0x170280a00 H:[UIImageView:0x1701fab00(44)]>",
    "<NSLayoutConstraint:0x170280c80 H:|-(10)-[UIImageView:0x1701fab00]   (Names: '|':UIView:0x1701822f0 )>",
    "<NSLayoutConstraint:0x170280dc0 H:[UIImageView:0x1701fab00]-(10)-[UILabel:0x155e5cd10'detailLbl']>",
    "<NSLayoutConstraint:0x170280e60 H:[UILabel:0x155e5cd10'detailLbl']-(10)-|   (Names: '|':UIView:0x1701822f0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x17409f180 h=--& v=--& H:[UIView:0x1701822f0(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170280a00 H:[UIImageView:0x1701fab00(44)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-10-25 18:28:14.280 Air Plan[1579:580797] 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:0x170281090 H:[UIImageView:0x1701fae00(44)]>",
    "<NSLayoutConstraint:0x170281310 H:|-(10)-[UIImageView:0x1701fae00]   (Names: '|':UIView:0x170182220 )>",
    "<NSLayoutConstraint:0x1702813b0 H:[UIImageView:0x1701fae00]-(10)-[UILabel:0x155e5d620'titleLbl']>",
    "<NSLayoutConstraint:0x170281400 H:[UILabel:0x155e5d620'titleLbl']-(10)-|   (Names: '|':UIView:0x170182220 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x17409fd60 h=--& v=--& H:[UIView:0x170182220(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170281090 H:[UIImageView:0x1701fae00(44)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2014-10-25 18:28:14.282 Air Plan[1579:580797] 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:0x170281b80 H:[UIImageView:0x1701fb100(44)]>",
    "<NSLayoutConstraint:0x17409f4a0 H:|-(10)-[UIImageView:0x1701fb100]   (Names: '|':UIView:0x170182150 )>",
    "<NSLayoutConstraint:0x17409f5e0 H:[UIImageView:0x1701fb100]-(10)-[UILabel:0x155d64210'detailLbl']>",
    "<NSLayoutConstraint:0x17409f680 H:[UILabel:0x155d64210'detailLbl']-(10)-|   (Names: '|':UIView:0x170182150 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x1742800f0 h=--& v=--& H:[UIView:0x170182150(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170281b80 H:[UIImageView:0x1701fb100(44)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

【问题讨论】:

【参考方案1】:

我也遇到了这个问题,并通过在 UICollectionViewCell 子类中添加它来解决它:

SWIFT >= 4.2

override func awakeFromNib() 
    contentView.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]

SWIFT 3

override func awakeFromNib() 
    contentView.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]

OBJC

- (void)awakeFromNib
    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Xcode 6.1 ios 8.0.2、8.1

您也可以查看这个答案:UICollectionView Cell + UiLabel with AutoLayout

【讨论】:

目前对于 swift 应该更像:override func awakeFromNib() super.awakeFromNib() contentView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight] 【参考方案2】:

在创建单元格后,单元格的内容视图为 50x50(与集合布局设置的大小无关)。

在单元格大小正确但内容视图仍为 50x50 后,自动布局第一次工作。应该是 iOS 8 的问题。其他布局适用于正确的内容视图大小。如此精细,您可以看到正确的布局,但日志输出却乱七八糟。

只需在 awakeFromNib 中将任何大于最小单元格大小的框架设置为 iOS 8 的内容视图。

你的情况

|-(10px)-UIImageView(44px)-(10px)-UILabel-(10px)-|

最小单元格宽度为 74 - 所有显式常量的总和。

- (void)awakeFromNib 
    [super awakeFromNib];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.) 
        self.contentView.frame = CGRectMake(0, 0, 200, 100);
    

有同样的问题,但设置 auoresizingMask 不起作用。 设置框架解决了这个问题。

【讨论】:

设置 cell.contentView.frame 明确解决了我的问题。非常感谢您抽出宝贵时间发帖。【参考方案3】:

我也有这个问题。添加:

[self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];

破坏了我的视图布局。就我而言,我不得不调整几个布局约束以使视图恢复到我想要的方式。在一种情况下,图像没有垂直居中,因为单元格的高度没有受到足够的约束。 (在那里,我向单元格中的最低元素添加了底部约束)。在另一种情况下,另一个图像(在不同的单元格中)没有居中,我必须进行不同的约束更改。我在该图像上添加了高度约束,并删除了顶部约束并解决了问题。

我在UILabels 的这两个单元格中也遇到了问题,这些问题不再受限于集合视图单元格的宽度。也就是说,当文本太长时,文本不会在单元格内很好地用“...”拖尾,它只会越过单元格的末尾。在这两种情况下,我能想出的唯一解决方法是为标签添加一个固定宽度的约束,从而使标签的宽度不具有自适应性。在将 translatesAutoresizingMaskIntoConstraints 设置为 NO 之前,之前存在的尾随约束有效。

【讨论】:

以上是关于UICollectionViewCell 自动布局的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewCell 和自动布局缩放

UITableView 单元内的 UICollectionViewCell 和自动布局

具有自动布局的全屏 UICollectionViewCell

自动布局:无法获取 UICollectionViewCell 子视图的帧大小

具有可变图像大小和自动布局的 UICollectionViewCell

在布局之间制作动画时,自动布局不会调整 Uicollectionviewcell 项目的大小