如何以编程方式向 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,因为有多种不同的方式可以通过编程方式添加自动布局约束,因此请查看您更喜欢哪种方式
更新截图
上面的配置是这样的
我以编程方式创建了一个带有 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,因为有多种不同的方式可以通过编程方式添加自动布局约束,因此请查看您更喜欢哪种方式
更新截图
上面的配置是这样的