为什么在调试视图层次结构时会出现这些布局问题,而模拟器中的 UI 布局还可以
Why these layout issues occur when debugging view hierarchy while the UI layout in simulator is OK
我使用视觉格式在单元格中布局子视图,如下所示:
contentView.addSubview(accountLabel)
contentView.addSubview(contentLabel)
contentView.addSubview(timeLabel)
let views: [String : Any] = [
"accountLabel": accountLabel,
"contentLabel": contentLabel,
"timeLabel": timeLabel
]
let hConstraint1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-15-[accountLabel]-[timeLabel]-8-|", options: [.alignAllCenterY], metrics: nil, views: views)
let hConstraint2 = NSLayoutConstraint.constraints(withVisualFormat: "H:[contentLabel]-8-|", options: [], metrics: nil, views: views)
let vConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-12-[accountLabel]-8-[contentLabel]-12-|", options: [.alignAllLeading], metrics: nil, views: views)
NSLayoutConstraint.activate(hConstraint1+hConstraint2+vConstraint)
在模拟器中 运行 时看起来还不错:
但是,调试视图层次结构时会出现一些布局问题:
为什么在 运行 时间 UI 看起来正常的情况下会出现这些布局问题?
上面的视觉格式字符串有问题吗?还是Xcode的bug?
如何解决这些布局问题?
好吧,我不是有限制的专家,但我确实看到了一个 "correctable" 问题和一个 "that's just weird maybe it's a bug" 问题。
据我了解,自动布局将尝试满足约束条件——即使它们不明确。如果它 失败 ,那么您会在控制台中看到错误消息,通常是 "will attempt to satisfy by breaking..."
因此您在 Debug View Hierarchy
中看到的警告信息比 "fix this error" 指令更具信息性。
也就是说...
您有 accountLabel
和 timeLabel
相对约束,但它们都具有相同的 Compression Resistance
。因此,只要每个标签中的文本量 "fit",就可以了。
但是假设 accountLabel
得到的文本字符串是 "This user name is too long to fit here"?
它应该是这样的吗(我使用背景颜色来帮助查看框架):
或者像这样:
这就是水平位置和宽度显示为 "ambiguous" 的原因。
您可以通过添加一行来解决该问题。假设您希望 accountLabel
被截断:
accountLabel.setContentCompressionResistancePriority(749, for: .horizontal)
会成功的。默认值为 750
,因此该行告诉自动布局给予 timeLabel
更高的阻力。
显示为不明确的高度和垂直位置似乎不正确。我没有发现约束有任何问题。
如果我对所有三个标签使用相同的字体? 没有 不明确的警告。
如果我为 timeLabel
使用不同的字体大小(如您在图片中显示的那样),现在 是 调试视图层次结构中的警告。
除了... 如果我滚动以便重复使用单元格?警告已消失!
编辑: 正如 OP 在他的评论中所述,可以通过为 [=13= 提供不同的 Content Hugging Priority
值来消除垂直歧义(在滚动之前) ] 和 contentLabel
.
因为默认的 Hugging
优先级是 250
:
accountLabel.setContentHuggingPriority(249, for: .vertical)
清除该警告。
我不认为它是必要的...但它确实似乎可以完成这项工作。
我使用视觉格式在单元格中布局子视图,如下所示:
contentView.addSubview(accountLabel)
contentView.addSubview(contentLabel)
contentView.addSubview(timeLabel)
let views: [String : Any] = [
"accountLabel": accountLabel,
"contentLabel": contentLabel,
"timeLabel": timeLabel
]
let hConstraint1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-15-[accountLabel]-[timeLabel]-8-|", options: [.alignAllCenterY], metrics: nil, views: views)
let hConstraint2 = NSLayoutConstraint.constraints(withVisualFormat: "H:[contentLabel]-8-|", options: [], metrics: nil, views: views)
let vConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-12-[accountLabel]-8-[contentLabel]-12-|", options: [.alignAllLeading], metrics: nil, views: views)
NSLayoutConstraint.activate(hConstraint1+hConstraint2+vConstraint)
在模拟器中 运行 时看起来还不错:
但是,调试视图层次结构时会出现一些布局问题:
为什么在 运行 时间 UI 看起来正常的情况下会出现这些布局问题?
上面的视觉格式字符串有问题吗?还是Xcode的bug?
如何解决这些布局问题?
好吧,我不是有限制的专家,但我确实看到了一个 "correctable" 问题和一个 "that's just weird maybe it's a bug" 问题。
据我了解,自动布局将尝试满足约束条件——即使它们不明确。如果它 失败 ,那么您会在控制台中看到错误消息,通常是 "will attempt to satisfy by breaking..."
因此您在 Debug View Hierarchy
中看到的警告信息比 "fix this error" 指令更具信息性。
也就是说...
您有 accountLabel
和 timeLabel
相对约束,但它们都具有相同的 Compression Resistance
。因此,只要每个标签中的文本量 "fit",就可以了。
但是假设 accountLabel
得到的文本字符串是 "This user name is too long to fit here"?
它应该是这样的吗(我使用背景颜色来帮助查看框架):
或者像这样:
这就是水平位置和宽度显示为 "ambiguous" 的原因。
您可以通过添加一行来解决该问题。假设您希望 accountLabel
被截断:
accountLabel.setContentCompressionResistancePriority(749, for: .horizontal)
会成功的。默认值为 750
,因此该行告诉自动布局给予 timeLabel
更高的阻力。
显示为不明确的高度和垂直位置似乎不正确。我没有发现约束有任何问题。
如果我对所有三个标签使用相同的字体? 没有 不明确的警告。
如果我为 timeLabel
使用不同的字体大小(如您在图片中显示的那样),现在 是 调试视图层次结构中的警告。
除了... 如果我滚动以便重复使用单元格?警告已消失!
编辑: 正如 OP 在他的评论中所述,可以通过为 [=13= 提供不同的 Content Hugging Priority
值来消除垂直歧义(在滚动之前) ] 和 contentLabel
.
因为默认的 Hugging
优先级是 250
:
accountLabel.setContentHuggingPriority(249, for: .vertical)
清除该警告。
我不认为它是必要的...但它确实似乎可以完成这项工作。