为啥父 UIStackView 无法识别子 StackView 的高度?
Posted
技术标签:
【中文标题】为啥父 UIStackView 无法识别子 StackView 的高度?【英文标题】:Why does parent UIStackView not recognize child StackView's height?为什么父 UIStackView 无法识别子 StackView 的高度? 【发布时间】:2020-08-11 13:15:28 【问题描述】:我正在尝试将包含多个标签的 xib 中的 UIStackView 加载到父 UIStackView 中。子堆栈中的标签通过模型对象在 viewDidLoad
方法中的 ViewController 之后填充值(或隐藏)。
我希望父 stackview 能够识别子 stackview 固有高度的变化,从而将兄弟视图向下移动。但是,下一个视图(按钮)覆盖了子堆栈的内容。为什么父级不能识别子视图高度的这种变化?我没有看到任何错误消息、不明确的约束或冲突。
以下是错误的呈现方式以及视图在视图层次结构中的显示方式。
我试过了:
在子堆栈视图周围添加一个 UIView 包装器,以查看父级是否会注册其高度的更改。 将所有代码移到父视图控制器中,避免加载 xib,这似乎确实有效,但代价是失去了模块化和关注点分离。 根据其他文章建议对子堆栈视图添加了可选的高度限制,导致位置不随内容弯曲,或无法解决原始问题。这是故事板布局
父视图控制器
class AcceptTermsViewController: RegistrationViewController
@IBOutlet weak var infoView: StackViewInBorderedView!
@IBOutlet weak var termsView: TermsTextView!
@IBOutlet weak var masterStack: UIStackView!
var registration: Registration?
override func viewDidLoad()
super.viewDidLoad()
self.configView()
self.setupNavBar()
func configView()
if let reg = registration
infoView.configView(reg)
子 StackView 代码
class StackViewInBorderedView: UIStackView
// loaded from NIB
private weak var view: UIView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var emailLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var postalLabel: UILabel!
@IBOutlet weak var idLabel: UILabel!
@IBOutlet weak var npiLabel: UILabel!
override init(frame: CGRect)
super.init(frame: frame)
loadViewFromNib()
required init(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
loadViewFromNib()
fileprivate func loadViewFromNib()
self.view = Bundle (for: type(of: self)).loadNibNamed(
"StackViewInBorderedView", owner: self, options: nil)! [0] as? UIView
view.frame = bounds
view.autoresizingMask = [.flexibleWidth]
self.addSubview(view)
override func layoutSubviews()
super.layoutSubviews()
self.layer.cornerRadius = 10
let shadowLayer = CAShapeLayer()
shadowLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.frame.height / 12).cgPath
shadowLayer.fillColor = UIColor.white.cgColor
shadowLayer.shadowColor = UIColor.gray.cgColor
shadowLayer.shadowOffset = CGSize.zero
shadowLayer.shadowOpacity = 1
shadowLayer.shadowRadius = 3
shadowLayer.masksToBounds = false
self.layer.insertSublayer(shadowLayer, at: 0)
func configView(_ reg: Registration)
configLabels(reg)
isLayoutMarginsRelativeArrangement = true
directionalLayoutMargins = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 0)
func configLabels(_ reg: Registration)
// Name line
if let degree = reg.degree
nameLabel.text = "\(reg.firstName!) \(reg.lastName!), \(degree)"
else
nameLabel.text = "\(reg.firstName!) \(reg.lastName!)"
// Title line
if let title = reg.title
titleLabel.text = title
else
titleLabel.isHidden = true
// Email line
if let email = reg.email
emailLabel.text = email
else
emailLabel.isHidden = true
// Location line
if let city = reg.city, let state = reg.state, let postal = reg.postalCode,
!city.isEmpty, !state.isEmpty, !postal.isEmpty
postalLabel.text = "\(city), \(state) \(postal)"
else if let postal = reg.postalCode
postalLabel.text = postal
// NPI line
if let licenseId = reg.licenseId
switch reg.countryCode
case "BR":
idLabel.text = "ID"
default:
idLabel.text = "NPI"
npiLabel.text = licenseId
else
self.idLabel.isHidden = true
self.npiLabel.isHidden = true
【问题讨论】:
我认为您需要为 MasterStack 中的所有子项添加顶部和底部约束 我认为这些约束是 masterstack 通过发行版自动添加的?我将其设置为等间距。 我猜你是对的,但只是注意到你的 MasterStack 没有底部约束,我认为这需要计算内在大小 好点。向 MasterStack 添加底部约束时,视图会被拉伸以填充安全区域。我的目标可能不明确。我想在主堆栈中的视图之间保持恒定的间距,并在按钮下方留下剩余的空白。 【参考方案1】:我的一位同事找到了答案。
从 nib 加载视图时,我需要调用 self.addArrangedSubview
而不是提供预期行为的 self.addSubview
。
【讨论】:
以上是关于为啥父 UIStackView 无法识别子 StackView 的高度?的主要内容,如果未能解决你的问题,请参考以下文章