UIStackView 中的项目未出现
Item in UIStackView not appearing
https://spin.atomicobject.com/2017/02/20/uistackview-stacking-child-views/
我正在按照本教程进行操作,以使视图相互堆叠并使用它们的固有内容大小。但是,当我将 Content Hugging Priority 应用于 signOffSignatureContainer 时,视图消失了,commentsContainer 占据了整个屏幕。
class AssessmentSignOffViewController: UIViewController, SignatureDrawingViewControllerDelegate {
private var signOffCommentsLabel: UILabel!
private var signOffCommentsTextView: UITextView!
private var signatureVCContainer: UIView!
private var signatureLabel: UILabel!
private var signatureViewController = SignatureDrawingViewController()
lazy var signOffSignatureContainer: UIView = { [unowned self] in
var signOffSignatureContainer = UIView()
signatureLabel = UILabel()
signatureVCContainer = UIView()
signOffSignatureContainer.translatesAutoresizingMaskIntoConstraints = false
signOffSignatureContainer.addSubview(signatureLabel)
signOffSignatureContainer.addSubview(clearSignatureButton)
signOffSignatureContainer.addSubview(signatureVCContainer)
// Signature Label
signatureLabel.text = "Signature"
signatureLabel.translatesAutoresizingMaskIntoConstraints = false
[signatureLabel.topAnchor.constraint(equalTo: signOffSignatureContainer.topAnchor, constant: 8),
signatureLabel.leadingAnchor.constraint(equalTo: signOffSignatureContainer.leadingAnchor, constant: 16)].forEach { [=10=].isActive = true }
// Signature Button
clearSignatureButton.addTarget(self, action: #selector(clearSignatureTapped), for: .touchUpInside)
clearSignatureButton.translatesAutoresizingMaskIntoConstraints = false
[clearSignatureButton.topAnchor.constraint(equalTo: signOffSignatureContainer.topAnchor, constant: 8),
clearSignatureButton.bottomAnchor.constraint(equalTo: signatureVCContainer.topAnchor, constant: 8),
clearSignatureButton.trailingAnchor.constraint(equalTo: signOffSignatureContainer.trailingAnchor, constant: -16)].forEach { [=10=].isActive = true }
// Signature Container
signatureVCContainer.layer.cornerRadius = 2.0
signatureVCContainer.layer.shadowColor = UIColor.gray.cgColor
signatureVCContainer.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
signatureVCContainer.layer.shadowRadius = 2.0
signatureVCContainer.layer.shadowOpacity = 0.5
signatureVCContainer.layer.borderWidth = 1
signatureVCContainer.layer.borderColor = UIColor.gray.cgColor
signatureVCContainer.clipsToBounds = true
signatureVCContainer.backgroundColor = .white
signOffSignatureContainer.setContentHuggingPriority(UILayoutPriority(249), for: .vertical)
signatureVCContainer.translatesAutoresizingMaskIntoConstraints = false
[signatureVCContainer.topAnchor.constraint(equalTo: signatureLabel.bottomAnchor, constant: 8),
signatureVCContainer.leadingAnchor.constraint(equalTo: signOffSignatureContainer.leadingAnchor, constant: 16),
signatureVCContainer.trailingAnchor.constraint(equalTo: signOffSignatureContainer.trailingAnchor, constant: -16),
signatureVCContainer.heightAnchor.constraint(equalToConstant: 300)].forEach { [=10=].isActive = true }
// Signature Controller
signatureVCContainer.addSubview(signatureViewController.view, stretchToFit: true)
signatureViewController.didMove(toParent: self)
signatureViewController.delegate = self
addChild(signatureViewController)
[signatureViewController.view.topAnchor.constraint(equalTo: signatureVCContainer.topAnchor, constant: 0),
signatureViewController.view.leadingAnchor.constraint(equalTo: signatureVCContainer.leadingAnchor, constant: 0),
signatureViewController.view.trailingAnchor.constraint(equalTo: signatureVCContainer.trailingAnchor, constant: 0),
signatureViewController.view.bottomAnchor.constraint(equalTo: signatureVCContainer.bottomAnchor, constant: 0)].forEach { [=10=].isActive = true }
return signOffSignatureContainer
}()
lazy var signOffCommentsContainer: UIView = { [unowned self] in
let signOffCommentsContainer = UIView()
signOffCommentsTextView = UITextView()
signOffCommentsLabel = UILabel()
signOffCommentsContainer.translatesAutoresizingMaskIntoConstraints = false
signOffCommentsContainer.addSubview(signOffCommentsLabel)
signOffCommentsContainer.addSubview(signOffCommentsTextView)
//signOffCommentsContainer.setContentHuggingPriority(UILayoutPriority(249), for: .vertical)
signOffCommentsLabel.text = "If you have any further sign off comments, please add them here."
signOffCommentsLabel.translatesAutoresizingMaskIntoConstraints = false
[signOffCommentsLabel.topAnchor.constraint(equalTo: signOffCommentsContainer.safeAreaLayoutGuide.topAnchor, constant: 16),
signOffCommentsLabel.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsLabel.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16)].forEach { [=10=].isActive = true }
signOffCommentsTextView.text = audit.notes
signOffCommentsTextView.delegate = self
signOffCommentsTextView.translatesAutoresizingMaskIntoConstraints = false
signOffCommentsTextView.placeholder = "Comments"
signOffCommentsTextView.font = UIFont.systemFont(ofSize: 17.0)
signOffCommentsTextView.layer.cornerRadius = 2.0
signOffCommentsTextView.layer.shadowColor = UIColor.gray.cgColor
signOffCommentsTextView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
signOffCommentsTextView.layer.shadowRadius = 2.0
signOffCommentsTextView.layer.shadowOpacity = 0.5
signOffCommentsTextView.layer.borderWidth = 1
signOffCommentsTextView.layer.borderColor = UIColor.gray.cgColor
[signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200)].forEach { [=10=].isActive = true }
return signOffCommentsContainer
}()
lazy var stackView: UIStackView = {
let sv = UIStackView(arrangedSubviews: [signOffCommentsContainer, signOffSignatureContainer])
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
sv.spacing = 16
sv.distribution = .fill
sv.alignment = .fill
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
}
fileprivate func setUpView() {
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
view.backgroundColor = .white
}
// MARK: SignatureDrawingViewControllerDelegate
func signatureDrawingViewControllerIsEmptyDidChange(controller: SignatureDrawingViewController, isEmpty: Bool) {
clearSignatureButton.isHidden = isEmpty
}
// MARK: Signature Functionality
private let clearSignatureButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("[Clear Signature]", for: .normal)
button.setTitleColor(UIColor.blue, for: .normal)
button.autoresizingMask = [.flexibleWidth, .flexibleHeight]
return button
}()
@objc private func clearSignatureTapped() {
signatureViewController.reset()
}
}
在您的 signOffCommentsContainer
中,您为内容添加了 Top、Leading、Trailing 和 Height 约束,但忘记添加 Bottom 约束。
您可以通过添加此行进一步了解:
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16)
在此区块中:
[signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200),
// add this line
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16)
].forEach { [=11=].isActive = true }
return signOffCommentsContainer
旁注...
您对视图、子视图和约束的组织有点难以理解。我建议按照以下几行对代码函数进行分组:
// disable .translatesAutoresizingMaskIntoConstraints
[signOffCommentsContainer, signOffCommentsLabel, signOffCommentsTextView].forEach {
[=12=].translatesAutoresizingMaskIntoConstraints = false
}
// group constraints logically
NSLayoutConstraint.activate([
// signOffCommentsLabel Top = 16, Leading = 16, Trailing = -16
signOffCommentsLabel.topAnchor.constraint(equalTo: signOffCommentsContainer.safeAreaLayoutGuide.topAnchor, constant: 16),
signOffCommentsLabel.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsLabel.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
// signOffCommentsTextView Top = 16, Leading = 16, Trailing = -16
// Height = 200, Bottom = -16
signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200),
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16.0)
])
我只是发现它更具可读性,并且更容易以这种方式遵循多元素约束关系。
https://spin.atomicobject.com/2017/02/20/uistackview-stacking-child-views/
我正在按照本教程进行操作,以使视图相互堆叠并使用它们的固有内容大小。但是,当我将 Content Hugging Priority 应用于 signOffSignatureContainer 时,视图消失了,commentsContainer 占据了整个屏幕。
class AssessmentSignOffViewController: UIViewController, SignatureDrawingViewControllerDelegate {
private var signOffCommentsLabel: UILabel!
private var signOffCommentsTextView: UITextView!
private var signatureVCContainer: UIView!
private var signatureLabel: UILabel!
private var signatureViewController = SignatureDrawingViewController()
lazy var signOffSignatureContainer: UIView = { [unowned self] in
var signOffSignatureContainer = UIView()
signatureLabel = UILabel()
signatureVCContainer = UIView()
signOffSignatureContainer.translatesAutoresizingMaskIntoConstraints = false
signOffSignatureContainer.addSubview(signatureLabel)
signOffSignatureContainer.addSubview(clearSignatureButton)
signOffSignatureContainer.addSubview(signatureVCContainer)
// Signature Label
signatureLabel.text = "Signature"
signatureLabel.translatesAutoresizingMaskIntoConstraints = false
[signatureLabel.topAnchor.constraint(equalTo: signOffSignatureContainer.topAnchor, constant: 8),
signatureLabel.leadingAnchor.constraint(equalTo: signOffSignatureContainer.leadingAnchor, constant: 16)].forEach { [=10=].isActive = true }
// Signature Button
clearSignatureButton.addTarget(self, action: #selector(clearSignatureTapped), for: .touchUpInside)
clearSignatureButton.translatesAutoresizingMaskIntoConstraints = false
[clearSignatureButton.topAnchor.constraint(equalTo: signOffSignatureContainer.topAnchor, constant: 8),
clearSignatureButton.bottomAnchor.constraint(equalTo: signatureVCContainer.topAnchor, constant: 8),
clearSignatureButton.trailingAnchor.constraint(equalTo: signOffSignatureContainer.trailingAnchor, constant: -16)].forEach { [=10=].isActive = true }
// Signature Container
signatureVCContainer.layer.cornerRadius = 2.0
signatureVCContainer.layer.shadowColor = UIColor.gray.cgColor
signatureVCContainer.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
signatureVCContainer.layer.shadowRadius = 2.0
signatureVCContainer.layer.shadowOpacity = 0.5
signatureVCContainer.layer.borderWidth = 1
signatureVCContainer.layer.borderColor = UIColor.gray.cgColor
signatureVCContainer.clipsToBounds = true
signatureVCContainer.backgroundColor = .white
signOffSignatureContainer.setContentHuggingPriority(UILayoutPriority(249), for: .vertical)
signatureVCContainer.translatesAutoresizingMaskIntoConstraints = false
[signatureVCContainer.topAnchor.constraint(equalTo: signatureLabel.bottomAnchor, constant: 8),
signatureVCContainer.leadingAnchor.constraint(equalTo: signOffSignatureContainer.leadingAnchor, constant: 16),
signatureVCContainer.trailingAnchor.constraint(equalTo: signOffSignatureContainer.trailingAnchor, constant: -16),
signatureVCContainer.heightAnchor.constraint(equalToConstant: 300)].forEach { [=10=].isActive = true }
// Signature Controller
signatureVCContainer.addSubview(signatureViewController.view, stretchToFit: true)
signatureViewController.didMove(toParent: self)
signatureViewController.delegate = self
addChild(signatureViewController)
[signatureViewController.view.topAnchor.constraint(equalTo: signatureVCContainer.topAnchor, constant: 0),
signatureViewController.view.leadingAnchor.constraint(equalTo: signatureVCContainer.leadingAnchor, constant: 0),
signatureViewController.view.trailingAnchor.constraint(equalTo: signatureVCContainer.trailingAnchor, constant: 0),
signatureViewController.view.bottomAnchor.constraint(equalTo: signatureVCContainer.bottomAnchor, constant: 0)].forEach { [=10=].isActive = true }
return signOffSignatureContainer
}()
lazy var signOffCommentsContainer: UIView = { [unowned self] in
let signOffCommentsContainer = UIView()
signOffCommentsTextView = UITextView()
signOffCommentsLabel = UILabel()
signOffCommentsContainer.translatesAutoresizingMaskIntoConstraints = false
signOffCommentsContainer.addSubview(signOffCommentsLabel)
signOffCommentsContainer.addSubview(signOffCommentsTextView)
//signOffCommentsContainer.setContentHuggingPriority(UILayoutPriority(249), for: .vertical)
signOffCommentsLabel.text = "If you have any further sign off comments, please add them here."
signOffCommentsLabel.translatesAutoresizingMaskIntoConstraints = false
[signOffCommentsLabel.topAnchor.constraint(equalTo: signOffCommentsContainer.safeAreaLayoutGuide.topAnchor, constant: 16),
signOffCommentsLabel.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsLabel.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16)].forEach { [=10=].isActive = true }
signOffCommentsTextView.text = audit.notes
signOffCommentsTextView.delegate = self
signOffCommentsTextView.translatesAutoresizingMaskIntoConstraints = false
signOffCommentsTextView.placeholder = "Comments"
signOffCommentsTextView.font = UIFont.systemFont(ofSize: 17.0)
signOffCommentsTextView.layer.cornerRadius = 2.0
signOffCommentsTextView.layer.shadowColor = UIColor.gray.cgColor
signOffCommentsTextView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
signOffCommentsTextView.layer.shadowRadius = 2.0
signOffCommentsTextView.layer.shadowOpacity = 0.5
signOffCommentsTextView.layer.borderWidth = 1
signOffCommentsTextView.layer.borderColor = UIColor.gray.cgColor
[signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200)].forEach { [=10=].isActive = true }
return signOffCommentsContainer
}()
lazy var stackView: UIStackView = {
let sv = UIStackView(arrangedSubviews: [signOffCommentsContainer, signOffSignatureContainer])
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
sv.spacing = 16
sv.distribution = .fill
sv.alignment = .fill
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
}
fileprivate func setUpView() {
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
view.backgroundColor = .white
}
// MARK: SignatureDrawingViewControllerDelegate
func signatureDrawingViewControllerIsEmptyDidChange(controller: SignatureDrawingViewController, isEmpty: Bool) {
clearSignatureButton.isHidden = isEmpty
}
// MARK: Signature Functionality
private let clearSignatureButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("[Clear Signature]", for: .normal)
button.setTitleColor(UIColor.blue, for: .normal)
button.autoresizingMask = [.flexibleWidth, .flexibleHeight]
return button
}()
@objc private func clearSignatureTapped() {
signatureViewController.reset()
}
}
在您的 signOffCommentsContainer
中,您为内容添加了 Top、Leading、Trailing 和 Height 约束,但忘记添加 Bottom 约束。
您可以通过添加此行进一步了解:
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16)
在此区块中:
[signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200),
// add this line
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16)
].forEach { [=11=].isActive = true }
return signOffCommentsContainer
旁注...
您对视图、子视图和约束的组织有点难以理解。我建议按照以下几行对代码函数进行分组:
// disable .translatesAutoresizingMaskIntoConstraints
[signOffCommentsContainer, signOffCommentsLabel, signOffCommentsTextView].forEach {
[=12=].translatesAutoresizingMaskIntoConstraints = false
}
// group constraints logically
NSLayoutConstraint.activate([
// signOffCommentsLabel Top = 16, Leading = 16, Trailing = -16
signOffCommentsLabel.topAnchor.constraint(equalTo: signOffCommentsContainer.safeAreaLayoutGuide.topAnchor, constant: 16),
signOffCommentsLabel.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsLabel.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
// signOffCommentsTextView Top = 16, Leading = 16, Trailing = -16
// Height = 200, Bottom = -16
signOffCommentsTextView.topAnchor.constraint(equalTo: signOffCommentsLabel.bottomAnchor, constant: 16),
signOffCommentsTextView.leadingAnchor.constraint(equalTo: signOffCommentsContainer.leadingAnchor, constant: 16),
signOffCommentsTextView.trailingAnchor.constraint(equalTo: signOffCommentsContainer.trailingAnchor, constant: -16),
signOffCommentsTextView.heightAnchor.constraint(equalToConstant: 200),
signOffCommentsTextView.bottomAnchor.constraint(equalTo: signOffCommentsContainer.bottomAnchor, constant: -16.0)
])
我只是发现它更具可读性,并且更容易以这种方式遵循多元素约束关系。