如何以编程方式向 stackView 添加约束

How to programmatically add constraints to a stackView

我以编程方式创建了一个带有 UISegmentedControl 的 stackView 和一个带有 MKMapView 的地图。我正在使用 CGRect 调整大小并将 stackView 的框架放置在界面中,但是当我切换设备模拟器时,stackView 会移动,因为它没有任何约束。我通常使用 StoryBoard 来为任何东西添加约束,但我自己从未以编程方式完成它。我在 Stack Overflow 中看到了其他示例,但到目前为止,它对我正在尝试做的事情没有帮助。 这是我的代码,展示了我如何在 viewDidLoad() 中显示它。如果有人可以解释如何以编程方式添加约束,以便 stackView 覆盖屏幕 Y 的 1/4 axis:547,谢谢。

import UIKit
import MapKit

class SampleViewController: UIViewController {


override func viewDidLoad() {
    super.viewDidLoad()
    
    let paddedStackView = UIStackView(arrangedSubviews: [segmentedControl])
    paddedStackView.layoutMargins = .init(top: 12, left: 12, bottom: 6, right: 12)
    paddedStackView.isLayoutMarginsRelativeArrangement = true
    
    let stackView = UIStackView(arrangedSubviews: [
        paddedStackView, map
        ])
    stackView.axis = .vertical
    view.addSubview(stackView)
    
    stackView.frame =  CGRect(x: 0, y: 547, width: 390, height: 350)

}

let map = MKMapView()

let segmentedControl:UISegmentedControl = {
    let sc = UISegmentedControl(items: ["Arriving", "Leaving"])
    sc.selectedSegmentIndex = 0
    sc.addTarget(self, action: #selector(handleSegmentControl), for: .valueChanged)
    return sc
}()

  @objc func handleSegmentControl(){
    
    switch segmentedControl.selectedSegmentIndex {
    case 0:
        print("Entered Destination")
    case 1:
        print("Exited Destination")
    default:
        print("Error")
    }

}
    //MARK: UIStackView
    
    let stackview = UIStackView()
    stackview.axis = .vertical
    stackview.spacing = 2
    stackview.distribution = .fill
    
    //MARK: Stackview Elements
    let view_left = UIView()
    let view_right = UIView()
    
    //MARK: initial added View
    stackview.addArrangedSubview(view_left)
    stackview.addArrangedSubview(view_right)
    
    //MARK: remove Run time stack elements
    
    for view in stackview.subviews {
        view.removeFromSuperview()
    }
    
   //MARK: Again assign values Run time
    
    stackview.insertArrangedSubview(view_right, at: 0)
    stackview.insertArrangedSubview(view_left, at: 1)

如果您的问题是如何转换:

stackView.frame =  CGRect(x: 0, y: 547, width: 390, height: 350)

并将高度设为 1/4 of the screen 而不是 350

将此请求转换为自动布局约束会像这样

private func configureStackView()
{
    let paddedStackView = UIStackView(arrangedSubviews: [segmentedControl])
    paddedStackView.layoutMargins = .init(top: 12,
                                          left: 12,
                                          bottom: 6,
                                          right: 12)
    
    paddedStackView.isLayoutMarginsRelativeArrangement = true
    
    let stackView = UIStackView(arrangedSubviews: [paddedStackView, map])
    stackView.axis = .vertical
    view.addSubview(stackView)
    
    // AUTO LAYOUT
    
    // This is important for using auto layout
    // Setting this to false means the frame is ignored
    // So sizing and positioning should be set by NSLayoutConstraints
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    // Add the view to its parent before adding any constraints
    view.addSubview(stackView)
    
    // Add constraints equivalent to:
    // CGRect(x: 0, y: 547, width: 390, height: 350)
    view.addConstraints([
        // this is x origin
        stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        
        // this is y origin
        stackView.topAnchor.constraint(equalTo: view.topAnchor,
                                       constant: 547),
        
        // this is the width
        stackView.widthAnchor.constraint(equalToConstant: 390),
        
        // this is height, thanks to @flanker for this update
        stackView.heightAnchor.constraint(equalTo: view.heightAnchor,
                                          multiplier: 0.75)
    ])
}

这应该能满足您的需求。

话虽如此,您可能想查看 this SO thread,因为有多种不同的方式可以通过编程方式添加自动布局约束,因此请查看您更喜欢哪种方式

更新截图

上面的配置是这样的