I am trying to put two UIViews inside a horizontal UIStackview. Inside the UIViews are Vertical UIStackviews to space the text (See picture for example). The vertical stackviews in the UIView is working. When I try to add the two UIViews to the horizontal stackview the UIViews are getting overlapped and I cant seem to space them properly. How can I space it like the example. I can't see the problem in the constraints. I tried a lot of different solutions but I cant figure it out.
Declarations
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
}()
Functions with constraints
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)
}
I appreciate all help.
First, you have a very odd constraint line:
horizontalStackview.widthAnchor.constraint(equalToConstant: horizontalStackview.frame.width)
You're telling auto-layout to make the horizontal stackView width equal to its own width. That doesn't make any sense.
Second, while it can be valuable to split tasks into separate funcs, it can make it difficult to follow what's going on. I'd suggest starting with everything "in-line" -- along with comments about what the code should be doing -- and then break it up later if desired.
What we want to do is:
So far, that's pretty much what you've done.
Now, let's logically setup the elements:
then:
Review the way it is done here:
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),
])
}
}
and that gives us:
If that's not the exact result you want, I think you'll find it much easier to follow the structure and constraint setup by coding it this way.
Again, once you have the layout structure clarified and showing up as desired, you could then split sections of code into separate funcs (if you find a benefit to that).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.