自动布局我可以将 CenterY 与顶部和底部约束结合起来吗?
Posted
技术标签:
【中文标题】自动布局我可以将 CenterY 与顶部和底部约束结合起来吗?【英文标题】:Autolayout Can I combine CenterY with Top and Bottom Constraints? 【发布时间】:2020-01-23 08:31:31 【问题描述】:我正在尝试使这种布局以某种方式动态化。这里的选项是动态的(数量未知),所以我们可以轻松地将这些选项放在 tableView、collectionView 或只是简单的 scrollView 中。
问题是我想让这个白色容器尽可能小并垂直居中。当我将 centerY 约束与 Top+Bottom 插入结合时,似乎只有顶部和底部约束被激活。
And when the options are quite long, options can be scrollable, BUT maintaining the fact that there are top and bottom insets.
我心里已经有了一些想法,比如观察容器视图的高度是否超过设备高度。
我使用 snapKit,但限制应该是可以理解的。这是我目前的布局:
func setupUI()
self.view.backgroundColor = .clear
self.view.addSubviews(
self.view_BGFilter,
self.view_Container
)
self.view_BGFilter.snp.makeConstraints
$0.edges.equalToSuperview()
self.view_Container.snp.makeConstraints
$0.centerY.equalToSuperview().priority(.high)
//$0.top.bottom.greaterThanOrEqualToSuperview().inset(80.0).priority(.medium)
$0.leading.trailing.equalToSuperview().inset(16.0)
// Setup container
self.view_Container.addSubviews(
self.label_Title,
self.stackView,
self.button_Submit
)
self.label_Title.snp.makeConstraints
$0.top.equalToSuperview().inset(40.0)
$0.leading.trailing.equalToSuperview().inset(16.0)
self.stackView.snp.makeConstraints
$0.top.equalTo(self.label_Title.snp.bottom).offset(29.0)
$0.leading.trailing.equalToSuperview().inset(24.0)
self.button_Submit.snp.makeConstraints
$0.height.equalTo(52.0)
$0.top.equalTo(self.stackView.snp.bottom).offset(30.0)
$0.bottom.leading.trailing.equalToSuperview().inset(24.0)
self.generateButtons()
【问题讨论】:
您是否希望选项按钮** 滚动(在需要时),将标题和确定按钮留在原处?还是您希望标题、选项按钮和 OKAAAAY 按钮全部滚动? 【参考方案1】:我回答你的问题 - 带有顶部和底部约束的 CenterY? - 附带一点评论...
我知道 SnapKit 很受欢迎,而且我敢肯定它有时会很有帮助,尤其是如果你一直使用它的话。
但是...在使用它时,您永远无法绝对确定它在做什么。而且,根据我的经验,使用 SnapKit 的人通常并不真正了解约束是什么或它们是如何工作的(并不意味着 you 就是这种情况......只是通过查看各种问题的观察) .
在这种特定情况下,要么 SnapKit 存在一些错误,要么此特定行不太适合所需的结果:
$0.top.bottom.greaterThanOrEqualToSuperview().inset(80.0)
你可以通过一个简单的测试来确认:
class TestViewController: UIViewController
let testView: UIView =
let v = UIView()
v.backgroundColor = .red
return v
()
override func viewDidLoad()
super.viewDidLoad()
view.addSubview(testView)
testView.snp.makeConstraints
$0.centerY.equalToSuperview()
// height exactly 200 points
$0.height.equalTo(200.0)
// top and bottom at least 80 points from superview
$0.top.bottom.greaterThanOrEqualToSuperview().inset(80.0)
$0.leading.trailing.equalToSuperview().inset(16.0)
这是结果...以及调试控制台中的[LayoutConstraints] Unable to simultaneously satisfy constraints.
消息:
如果我们将该行替换如下:
// replace this line
//$0.top.bottom.greaterThanOrEqualToSuperview().inset(80.0)
// with these two lines
$0.top.greaterThanOrEqualToSuperview().offset(80.0)
$0.bottom.lessThanOrEqualToSuperview().offset(-80.0)
当然似乎在做同样的事情,我们得到了我们所期望的:
所以,SnapKit 中的某些东西是可疑的。
这将解决您的问题。像这样更改您的 view_Container
约束设置:
self.view_Container.snp.makeConstraints
$0.centerY.equalToSuperview().priority(.required)
// replace this line
//$0.top.bottom.greaterThanOrEqualToSuperview().inset(80.0)
// with these two lines
$0.top.greaterThanOrEqualToSuperview().offset(80.0)
$0.bottom.lessThanOrEqualToSuperview().offset(-80.0)
$0.leading.trailing.equalToSuperview().inset(16.0)
改动前:
改动后:
至于当您有许多选项按钮时添加滚动,我可以举一个例子,滚动所有内容或滚动仅选项按钮。
【讨论】:
不错的发现!非常感谢!以上是关于自动布局我可以将 CenterY 与顶部和底部约束结合起来吗?的主要内容,如果未能解决你的问题,请参考以下文章