如何用SnapKit实现ContentView自适应内容尺寸?
用SnapKit实现AutoLayout中contentView的自适应高度约束
我在使用AutoLayout时,通过以下代码实现布局,其中的bottomAnchor约束用于让contentView自适应内容尺寸:
let safeAreaLayoutGuide = contentView.safeAreaLayoutGuide let bottomAnchor = userImage.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16.0) bottomAnchor.priority = .required - 1 NSLayoutConstraint.activate([ userImage.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16), userImage.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor , constant: 16), userImage.widthAnchor.constraint(equalToConstant: 90), userImage.heightAnchor.constraint(equalToConstant: 90), userName.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16), userName.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16), userName.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16), userStatus.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 16), userStatus.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16), userStatus.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16), textField.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 48), textField.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16), textField.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16), textField.heightAnchor.constraint(equalToConstant: 32), showStatusButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 16), showStatusButton.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 16), showStatusButton.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16), bottomAnchor ])
现在我尝试用SnapKit重构,已完成大部分控件的约束设置:
userImage.snp.makeConstraints { make in make.top.equalTo(self.safeAreaInsets.top).offset(16) make.left.equalTo(self.safeAreaInsets.left).offset(16) make.height.width.equalTo(userImage.layer.cornerRadius * 2) } userName.snp.makeConstraints { make in make.top.equalTo(self.safeAreaInsets.top).offset(16) make.left.equalTo(userImage.snp.right).offset(16) make.right.equalTo(self.safeAreaInsets.right).inset(-16) } userStatus.snp.makeConstraints { make in make.top.equalTo(userName.snp.bottom).offset(16) make.left.equalTo(userImage.snp.right).offset(16) make.right.equalTo(self.safeAreaInsets.right).offset(-16) } textField.snp.makeConstraints { make in make.top.equalTo(userStatus.snp.bottom).offset(40) make.left.equalTo(self.safeAreaInsets.left).offset(16) make.right.equalTo(self.safeAreaInsets.right).offset(-16) make.height.equalTo(32) } showStatusButton.snp.makeConstraints { make in make.top.equalTo(textField.snp.bottom).offset(16) make.left.equalTo(self.safeAreaInsets.left).offset(16) make.right.equalTo(self.safeAreaInsets.right).offset(-16) }
但不知道如何替代原来的bottomAnchor,实现contentView自适应内容(让其底部与showStatusButton的底部关联)。
解决方案
原来的bottomAnchor是一个低优先级约束,作用是兜底contentView的最小高度:当内部控件总高度不足时,让userImage底部距离safeArea底部保持16pt间距,避免contentView过矮;当内部控件(如showStatusButton)的高度足够撑高contentView时,这个约束会自动失效,contentView高度由最底部的控件决定。
在SnapKit中可以这样实现:
- 给
userImage添加低优先级的底部约束,对应原来的逻辑:
userImage.snp.makeConstraints { make in make.top.equalTo(contentView.snp.safeAreaLayoutGuideTop).offset(16) make.left.equalTo(contentView.snp.safeAreaLayoutGuideLeft).offset(16) make.height.width.equalTo(userImage.layer.cornerRadius * 2) // 保持你原来的设置,或者改为90和AutoLayout一致 // 添加低优先级底部约束,效果等同于原来的bottomAnchor make.bottom.lessThanOrEqualTo(contentView.snp.safeAreaLayoutGuideBottom).offset(-16).priority(.required - 1) }
- 确保
showStatusButton的布局能自然撑高contentView:
不需要给showStatusButton额外加底部约束,因为它是布局中最靠下的控件,自动布局会根据它的位置计算contentView的高度。如果你的contentView是UITableViewHeaderFooterView或UICollectionReusableView,只要内部约束完整,系统会自动计算其高度。
另外,建议把代码中self.safeAreaInsets替换为contentView.snp.safeAreaLayoutGuideTop/contentView.snp.safeAreaLayoutGuideLeft等,这样更贴合AutoLayout中原先使用safeAreaLayoutGuide的逻辑,避免因视图层级问题导致的约束错误。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

