Edwjonn
Edwjonn

Reputation: 171

Troubles with some layouts

I'm trying to put 2 buttons and one line separator between the 2 buttons. These 2 buttons and the line are inside an UIView called "customAlert". This is how i want it to looks like...

enter image description here

Here is what i have tried...

let boton1: UIButton = {
        let boton = UIButton(type: .system)
        boton.translatesAutoresizingMaskIntoConstraints = false
        boton.backgroundColor = .blue
        return boton
    }()

    let boton2: UIButton = {
        let boton = UIButton(type: .system)
        boton.backgroundColor = .yellow
        boton.translatesAutoresizingMaskIntoConstraints = false
        return boton
    }()

    let lineaSeparadora2: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .black
        return view
    }()

    customAlert.addSubview(boton1)
    customAlert.addSubview(boton2)
    customAlert.addSubview(lineaSeparadora2)

    boton1.topAnchor.constraint(equalTo: textfield1.bottomAnchor, constant: 4).isActive = true
    boton1.leftAnchor.constraint(equalTo: customAlert.leftAnchor, constant: 2).isActive = true
   // boton1.rightAnchor.constraint(equalTo: lineaSeparadora2.leftAnchor, constant: 0.5).isActive = true
    boton1.heightAnchor.constraint(equalToConstant: 50).isActive = true

    lineaSeparadora2.centerYAnchor.constraint(equalTo: textfield1.centerYAnchor, constant: 0).isActive = true
    lineaSeparadora2.leftAnchor.constraint(equalTo: customAlert.rightAnchor, constant: boton1.frame.size.width).isActive = true
    lineaSeparadora2.rightAnchor.constraint(equalTo: customAlert.leftAnchor, constant: boton2.frame.size.height).isActive = true
    lineaSeparadora2.bottomAnchor.constraint(equalTo: boton1.bottomAnchor, constant: 0)
    //lineaSeparadora2.widthAnchor.constraint(equalToConstant: 7).isActive = true

    boton2.topAnchor.constraint(equalTo: textfield1.bottomAnchor, constant: 4).isActive = true
    //boton2.leftAnchor.constraint(equalTo: lineaSeparadora2.rightAnchor, constant: 0.5).isActive = true
    boton2.rightAnchor.constraint(equalTo: customAlert.rightAnchor, constant: 2).isActive = true
    boton2.heightAnchor.constraint(equalToConstant: 50).isActive = true

Thanks for the help!!!

Upvotes: 0

Views: 48

Answers (2)

user7014451
user7014451

Reputation:

While there are other ways to draw a black separator, the objective looks to be (1) having a horizontal layout of three UIViews with (2) equal spacing between views #1, #2, and #3 along with (3) based on your drawing the same spacing between view #3 and the trailing margin.

Additionally, horizontal width is explicit in the layout. Also, vertical layout is not part of the issue.

The easiest answer is to use layoutGuides, as explained in this blog.

I'm not the best with visuals, but let me try. Horizontally, left to right, you want:

  • Leading edge
  • Spacer 1
  • View 1 (green)
  • Spacer 2
  • View 2 (separator)
  • Spacer 3
  • View 3 (blue)
  • Spacer 4

Speaking in terms of "4 spacers" is old school. Instead, let's speak in terms of "4 layoutGuides". The trick? Guides 2, 3, and 4 are the same width - and guide 1 is what it is. (At least by your drawing.)

// create four layout guides

var spacers = [UILayoutGuide]()
for _ in 0...3 {
    spacers.append(UILayoutGuide())
}

// line up all views & spacers horizontally

spacer[0].leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
greenView.leadingAnchor.constraint(equalTo: spacer[0].trailingAnchor).isActive = true
spacer[1].leadingAnchor.constraint(equalTo: greenView.trailingAnchor).isActive = true
separatorView.leadingAnchor.constraint(equalTo: spacer[1].trailingAnchor).isActive = true
spacer[2].leadingAnchor.constraint(equalTo: separatorView.trailingAnchor).isActive = true
blueView.leadingAnchor.constraint(equalTo: spacer[2].trailingAnchor).isActive = true
spacer[3].leadingAnchor.constraint(equalTo: blueView.trailingAnchor).isActive = true
spacer[3].trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

// set the widths of the views, for instance:

greenView.widthAnchor.constraint(equalToConstant: 100).isActive = true
separatorView.widthAnchor.constraint(equalToConstant: 5).isActive = true
blueView.widthAnchor.constraint(equalToConstant: 100).isActive = true

// set the widths of spacers 2, 3, and 4 equal to each other

spacers[1].widthAnchor.constraint(equalTo: spacers[3].widthAnchor).isActive = true
spacers[2].widthAnchor.constraint(equalTo: spacers[3].widthAnchor).isActive = true

// since you probably want *something* for a left margin, set the left-most spacer to an explicit width

spacers[0].widthAnchor.constraint(equalToConstant: 10).isActive = true

That's pretty much it. I've ignore anything vertical, and just focused on the horizontal. The keys are:

  • UILayoutGuides work *like a UIView but without the overhead.
  • After setting your leading/trailing layout, define widths. (You can get fancy and work with "greater than or equal to" and priorities also.)
  • Set the last 3 of 4 spacers to be equal in width but do not set an explicit width.
  • Set the left-most spacer (based on your drawing) to have a more explicit width than the other spacers.

Upvotes: 1

vacawama
vacawama

Reputation: 154691

Your main problem is that you can't use boton1.frame.size.width and boton2.frame.size.width as constants for your constraints, because at the time you create the constraint their values are 0.

Instead, I suggest you set a constraint to make boton1 and boton2 to have equal widths:

boton1.topAnchor.constraint(equalTo: textfield1.bottomAnchor, constant: 4).isActive = true
boton1.leftAnchor.constraint(equalTo: customAlert.leftAnchor, constant: 2).isActive = true
boton1.rightAnchor.constraint(equalTo: lineaSeparadora2.leftAnchor, constant: -10).isActive = true
boton1.heightAnchor.constraint(equalToConstant: 50).isActive = true

lineaSeparadora2.topAnchor.constraint(equalTo: boton1.topAnchor, constant: 0).isActive = true
lineaSeparadora2.bottomAnchor.constraint(equalTo: boton1.bottomAnchor, constant: 0).isActive = true
lineaSeparadora2.widthAnchor.constraint(equalToConstant: 7).isActive = true

boton2.topAnchor.constraint(equalTo: textfield1.bottomAnchor, constant: 4).isActive = true
boton2.leftAnchor.constraint(equalTo: lineaSeparadora2.rightAnchor, constant: 10).isActive = true
boton2.rightAnchor.constraint(equalTo: customAlert.rightAnchor, constant: -2).isActive = true
boton2.heightAnchor.constraint(equalToConstant: 50).isActive = true

boton1.widthAnchor.constraint(equalTo: boton2.widthAnchor).isActive = true

Upvotes: 2

Related Questions