简体   繁体   English

为什么父 UIStackView 无法识别子 StackView 的高度?

[英]Why does parent UIStackView not recognize child StackView's height?

I am trying to load a UIStackView from a xib that contains multiple labels into a parent UIStackView.我正在尝试将包含多个标签的 xib 中的 UIStackView 加载到父 UIStackView 中。 The labels in the child stack get populated with values (or hidden) after the ViewController in the viewDidLoad method via a model object.子堆栈中的标签通过 model object 在 vi viewDidLoad方法中的 ViewController 之后填充值(或隐藏)。

I expect that the parent stackview would recognize the change in intrinsic height of the child stackview, and thus move sibling views down.我希望父堆栈视图能够识别子堆栈视图固有高度的变化,从而将兄弟视图向下移动。 However, the next view (button) covers the content of the child stack.但是,下一个视图(按钮)覆盖了子堆栈的内容。 Why does the parent not recognize this change to a subview's height?为什么父级不能识别子视图高度的这种变化? I am not seeing any error messages, ambiguous constraints, or conflicts.我没有看到任何错误消息、模棱两可的约束或冲突。

Here is how the error renders and how the views appear in the View Hierarchy.以下是错误的呈现方式以及视图在视图层次结构中的显示方式。 在此处输入图像描述

I have tried:我努力了:

  • Adding a UIView wrapper around the child stack view to see if the parent would register the change in it's height.在子堆栈视图周围添加 UIView 包装器,以查看父级是否会注册其高度的更改。
  • Moved ALL the code into the parent view controller, avoiding xib loading and that does appear to work, at the cost of losing modularity and separation of concerns.将所有代码移到父视图 controller 中,避免加载 xib,这似乎确实有效,但代价是失去了模块化和关注点分离。
  • Added optional height constraints on the child stackview based on other article recommendations, resulting in the positions not flexing with the content, or not resolving the original issue.根据其他文章的建议对子 stackview 添加了可选的高度约束,导致位置不随内容弯曲,或者无法解决原始问题。

Here is the storyboard layout这是 storyboard 布局显示父堆栈(主堆栈)和子堆栈(信息视图)的情节提要

Parent View Controller父视图 Controller

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)
        }
    }
}

Child StackView Code子 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
        }
    }
}

A colleague of mine found the answer.我的一位同事找到了答案。

When loading the view from the nib, I needed to call self.addArrangedSubview instead of self.addSubview which provides the intended behavior.从笔尖加载视图时,我需要调用self.addArrangedSubview而不是self.addSubview来提供预期的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM