繁体   English   中英

Swift 如何以编程方式将垂直 UIStackview / UIView 放入水平 UIStackview

[英]Swift how to put vertical UIStackview / UIView inside horizontal UIStackview programatically

我正在尝试将两个 UIViews 放在一个水平 UIStackview 中。 UIViews 内部是垂直的 UIStackviews 来分隔文本(例如参见图片)。 UIView 中的垂直堆栈视图正在工作。 当我尝试将两个 UIViews 添加到水平 stackview 时,UIViews 正在重叠,我似乎无法正确分隔它们。 我怎样才能像这个例子一样隔开它。 我看不到约束中的问题。 我尝试了很多不同的解决方案,但我无法弄清楚。

在此处输入图像描述

声明

private let horizontalStackview: UIStackView = {
        let horizontalStackview = UIStackView()
        horizontalStackview.distribution = .fillEqually
        horizontalStackview.axis = .horizontal
        horizontalStackview.spacing = 200
        uhorizontalStackview.translatesAutoresizingMaskIntoConstraints = false
        return horizontalStackview
    }()
    
    private let verticalFirstUIView: UIView = {
        let verticalFirstUIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))
        verticalFirstUIView.backgroundColor = .white
        verticalFirstUIView.layer.borderWidth = 2
        verticalFirstUIView.layer.borderColor = UIColor.gray.cgColor
        verticalFirstUIView.translatesAutoresizingMaskIntoConstraints = false
        return verticalFirstUIView
    }()
    
    private let verticalSecondUIView: UIView = {
        let verticalSecondUIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))
        verticalSecondUIView.backgroundColor = .white
        verticalSecondUIView.layer.borderWidth = 2
        verticalSecondUIViewlayer.borderColor = UIColor.blue.cgColor
        verticalSecondUIView.translatesAutoresizingMaskIntoConstraints = false
        return verticalSecondUIView
    }()
    
    
    private let verticalFirstStackView: UIStackView = {
        let verticalFirstStackView = UIStackView()
       verticalFirstStackView.axis = .vertical
       verticalFirstStackView.alignment = .center
        verticalFirstStackViewdistribution = .fillEqually
        verticalFirstStackViewspacing = 5
        verticalFirstStackView.translatesAutoresizingMaskIntoConstraints = false
        return verticalFirstStackView
    }()
    
    private let verticalSecondStackView: UIStackView = {
        let verticalSecondStackView = UIStackView()
       verticalSecondStackView.axis = .vertical
        verticalSecondStackView.alignment = .center
        verticalSecondStackViewdistribution = .fillEqually
        verticalSecondStackView.spacing = 5
        verticalSecondStackView.translatesAutoresizingMaskIntoConstraints = false
        return verticalSecondStackView
    }()

有约束的函数

func setupHorizontalStackview(){
        view.addSubview(horizontalStackview)

        horizontalStackview.addArrangedSubview(verticalFirstUIView)
        horizontalStackview.addArrangedSubview(verticalSecondUIView)
        NSLayoutConstraint.activate([
           horizontalStackview.topAnchor.constraint(equalTo: labelAboveHorizontalStackView.bottomAnchor, constant: 10),
            horizontalStackview.widthAnchor.constraint(equalToConstant: horizontalStackview.frame.width)
        ])
    }
    

    func setupVerticalFirstUIView(){
        view.addSubview(verticalFirstUIView)
        userSavedUIView.addSubview(verticalFirstStackView)
        NSLayoutConstraint.activate([   verticalFirstUIView.topAnchor.constraint(equalTo: horizontalStackview.topAnchor),
            verticalFirstUIView.widthAnchor.constraint(equalToConstant: verticalFirstUIView.frame.width)
        ])
    }

    func setupVerticalSecondUIView(){
        view.addSubview(verticalSecondUIView)
       verticalSecondUIView.addSubview(verticalSecondStackView)
        NSLayoutConstraint.activate([
            verticalSecondUIView.topAnchor.constraint(equalTo: horizontalStackview.topAnchor),
            verticalSecondUIView.widthAnchor.constraint(equalToConstant: verticalSecondUIView.frame.width)
        ])
    }

    func setupverticalFirstStackView(){
        view.addSubview(verticalFirstStackView)
        NSLayoutConstraint.activate([
            verticalFirstStackView.leadingAnchor.constraint(equalTo: verticalFirstUIView.leadingAnchor, constant: 15),
           verticalFirstStackView.trailingAnchor.constraint(equalTo: verticalFirstUIView.trailingAnchor, constant: -15),
            verticalFirstStackView.topAnchor.constraint(equalTo: verticalFirstUIView.topAnchor, constant: 15),
            verticalFirstStackView.bottomAnchor.constraint(equalTo: verticalFirstUIView.bottomAnchor),
        ])

       let ulText = UILabel()
        let ulTextTwo = UILabel()
        let ulTextThree = UILabel()


    ulText.text = "text”
    ulTextTwo.text = "text2”
    ulTextThree.text = "text3”


        verticalFirstStackView.addArrangedSubview(ulText)
        verticalFirstStackView.addArrangedSubview(ulTextTwo)
        verticalFirstStackView.addArrangedSubview(ulTextThree)
    }



     func setupverticalSecondStackView(){
        view.addSubview(verticalSecondStackView)
        NSLayoutConstraint.activate([
            verticalSecondStackView.leadingAnchor.constraint(equalTo: verticalSecondUIView.leadingAnchor, constant: 15),
           verticalSecondStackView.trailingAnchor.constraint(equalTo: verticalSecondUIView.trailingAnchor, constant: -15),
            verticalSecondStackView.topAnchor.constraint(equalTo: verticalSecondUIView.topAnchor, constant: 15),
            verticalSecondStackView.bottomAnchor.constraint(equalTo: verticalSecondUIView.bottomAnchor),
        ])

       let ulText = UILabel()
        let ulTextTwo = UILabel()
        let ulTextThree = UILabel()


    ulText.text = "text”
    ulTextTwo.text = "text2”
    ulTextThree.text = "text3”


       verticalSecondStackView.addArrangedSubview(ulText)
        verticalSecondStackView.addArrangedSubview(ulTextTwo)
        verticalSecondStackView.addArrangedSubview(ulTextThree)
}

我感谢所有帮助。

首先,您有一条非常奇怪的约束线:

horizontalStackview.widthAnchor.constraint(equalToConstant: horizontalStackview.frame.width)

你告诉自动布局使水平 stackView 宽度等于它自己的宽度。 这没有任何意义。

其次,虽然将任务拆分为单独的功能可能很有价值,但它可能会让人难以理解正在发生的事情。 我建议“内联”的所有内容开始——以及关于代码应该做什么的评论——然后如果需要,稍后再分解。

我们要做的是:

  • 声明“水平堆栈视图上方的标签”
  • 声明水平堆栈视图
  • 声明两个垂直堆栈视图
  • 声明两个“UI”视图(包含垂直堆栈视图)

到目前为止,这几乎就是你所做的。

现在,让我们在逻辑上设置元素:

  • 为每个垂直堆栈视图添加三个标签
  • 将这些堆栈视图添加到它们各自的“UI”视图中
  • 将每个堆栈视图约束到其“UI”视图
  • 将两个“UI”视图添加到水平堆栈视图

然后:

  • 将 label 添加到视图中
  • 将水平堆栈视图添加到视图
  • 为 label 添加约束
  • 为水平堆栈视图添加约束

在此处查看其完成方式:

class ViewController: UIViewController {
    
    // a label above the horizontal stack view
    private let labelAboveHorizontalStackView: UILabel = {
        let v = UILabel()
        v.text = "Label above stack view"
        v.textAlignment = .center
        v.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    private let horizontalStackview: UIStackView = {
        let horizontalStackview = UIStackView()
        horizontalStackview.distribution = .fillEqually
        horizontalStackview.axis = .horizontal
        horizontalStackview.spacing = 200
        horizontalStackview.translatesAutoresizingMaskIntoConstraints = false
        return horizontalStackview
    }()
    
    private let verticalFirstUIView: UIView = {
        let verticalFirstUIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))
        verticalFirstUIView.backgroundColor = .white
        verticalFirstUIView.layer.borderWidth = 2
        verticalFirstUIView.layer.borderColor = UIColor.gray.cgColor
        verticalFirstUIView.translatesAutoresizingMaskIntoConstraints = false
        return verticalFirstUIView
    }()
    
    private let verticalSecondUIView: UIView = {
        let verticalSecondUIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))
        verticalSecondUIView.backgroundColor = .white
        verticalSecondUIView.layer.borderWidth = 2
        verticalSecondUIView.layer.borderColor = UIColor.blue.cgColor
        verticalSecondUIView.translatesAutoresizingMaskIntoConstraints = false
        return verticalSecondUIView
    }()
    
    private let verticalFirstStackView: UIStackView = {
        let verticalFirstStackView = UIStackView()
        verticalFirstStackView.axis = .vertical
        verticalFirstStackView.alignment = .center
        verticalFirstStackView.distribution = .fillEqually
        verticalFirstStackView.spacing = 5
        verticalFirstStackView.translatesAutoresizingMaskIntoConstraints = false
        return verticalFirstStackView
    }()
    
    private let verticalSecondStackView: UIStackView = {
        let verticalSecondStackView = UIStackView()
        verticalSecondStackView.axis = .vertical
        verticalSecondStackView.alignment = .center
        verticalSecondStackView.distribution = .fillEqually
        verticalSecondStackView.spacing = 5
        verticalSecondStackView.translatesAutoresizingMaskIntoConstraints = false
        return verticalSecondStackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // add 3 labels to each vertical stack view
        [verticalFirstStackView, verticalSecondStackView].forEach { sv in
            let ulText = UILabel()
            let ulTextTwo = UILabel()
            let ulTextThree = UILabel()

            ulText.text = "text"
            ulTextTwo.text = "text2"
            ulTextThree.text = "text3"

            // let's give the labels a background color to easily see the layout
            ulText.backgroundColor = .yellow
            ulTextTwo.backgroundColor = .green
            ulTextThree.backgroundColor = .cyan

            sv.addArrangedSubview(ulText)
            sv.addArrangedSubview(ulTextTwo)
            sv.addArrangedSubview(ulTextThree)
        }
        
        // add each vertical stack view as a subview of "UI" views
        verticalFirstUIView.addSubview(verticalFirstStackView)
        verticalSecondUIView.addSubview(verticalSecondStackView)
        
        // constrain the stack views to the "UI" views
        //  with 15-pts "padding" on Top / Leading / Trailing
        NSLayoutConstraint.activate([
            verticalFirstStackView.topAnchor.constraint(equalTo: verticalFirstUIView.topAnchor, constant: 15.0),
            verticalFirstStackView.leadingAnchor.constraint(equalTo: verticalFirstUIView.leadingAnchor, constant: 15.0),
            verticalFirstStackView.trailingAnchor.constraint(equalTo: verticalFirstUIView.trailingAnchor, constant: -15.0),
            verticalFirstStackView.bottomAnchor.constraint(equalTo: verticalFirstUIView.bottomAnchor, constant: 0.0),

            verticalSecondStackView.topAnchor.constraint(equalTo: verticalSecondUIView.topAnchor, constant: 15.0),
            verticalSecondStackView.leadingAnchor.constraint(equalTo: verticalSecondUIView.leadingAnchor, constant: 15.0),
            verticalSecondStackView.trailingAnchor.constraint(equalTo: verticalSecondUIView.trailingAnchor, constant: -15.0),
            verticalSecondStackView.bottomAnchor.constraint(equalTo: verticalSecondUIView.bottomAnchor, constant: 0.0),
        ])
        
        // add the two "UI" views to the horizontal stack view
        horizontalStackview.addArrangedSubview(verticalFirstUIView)
        horizontalStackview.addArrangedSubview(verticalSecondUIView)
        
        // add the "above label" to the view
        view.addSubview(labelAboveHorizontalStackView)
        
        // add horizontal stack view to the view
        view.addSubview(horizontalStackview)

        // let's respect the safe area
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // label 40-pts from top
            labelAboveHorizontalStackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            // label centered horizontally
            labelAboveHorizontalStackView.centerXAnchor.constraint(equalTo: g.centerXAnchor),

            // stack view 10-pts below label
            horizontalStackview.topAnchor.constraint(equalTo: labelAboveHorizontalStackView.bottomAnchor, constant: 10.0),
            
            // allow the arranged subviews to determine the width?
            // if yes, center the horizontal stack view
            horizontalStackview.centerXAnchor.constraint(equalTo: g.centerXAnchor),

            // let's make the "above label" the same width as the
            //  resulting width of the horizontal stack view
            labelAboveHorizontalStackView.widthAnchor.constraint(equalTo: horizontalStackview.widthAnchor),
            
        ])
        
    }
    
}

这给了我们:

在此处输入图像描述

如果这不是您想要的确切结果,我认为您会发现通过这种方式编码更容易遵循结构和约束设置。

同样,一旦您根据需要阐明并显示了布局结构,您就可以将代码部分拆分为单独的函数(如果您发现这样做有好处)。

暂无
暂无

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

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