0

I want to create multiple buttons and position it inside uiview and fit to uiview.(as picture)

I need to get uiview frame to calculate and divide as I need , to set button's width and height depending on device size.

        for row in 0 ..< 4 {
        for col in 0..<3 {
            let numberButton = UIButton()
            numberButton.frame = CGRect(x: Int(buttonView.frame.width / 3 - 20) * col, y: row * (320 / 4), width: Int(buttonView.frame.width) / 3, height: Int(buttonView.frame.height) / 4)
            numberButton.setTitle("button", for: .normal)
            numberButton.titleLabel?.font = numberButton.titleLabel?.font.withSize(30)
            numberButton.setTitleColor(UIColor.black)

            buttonView.addSubview(numberButton)
        }

    }

I tried like code above, but buttonView.frame.width returns nil.

How can I calculate this view's frame?

enter image description here

alphonse
  • 687
  • 1
  • 6
  • 16
  • This is a great opportunity to use `UIStackView`. – Sweeper Jul 09 '20 at 04:45
  • @Sweeper So How could I get superview's height to set stackview's height? – alphonse Jul 09 '20 at 04:51
  • You are taking the wrong approach really. You should not need to calculate the height/width of each button. You should instead use AutoLayout and Stack Views, which will calculate the frames of views automatically for you, and help you adapt your layout to different screen sizes. – Sweeper Jul 09 '20 at 04:56
  • I think you misunderstood. `buttonView` would be the `UIStackView`. You just need to add constraints to `buttonView` (recommended) or set `buttonView.frame` to something, and then the button's frames will change automatically. See my answer. – Sweeper Jul 09 '20 at 05:08

1 Answers1

1

You can use UIStackViews to achieve this grid layout. This way, you don't have to calculate the frames of each button. Doing so is bad practice anyway. You should instead use AutoLayout constraints to layout your views. Here's a tutorial to get you started.

Anyway, here's how you would use UIStackViews to create a grid of buttons:

// here I hardcoded the frame of the button view, but in reality you should add
// AutoLayout constraints to it to specify its frame
let buttonView = UIStackView(frame: CGRect(x: 0, y: 0, width: 600, height: 320))
buttonView.alignment = .fill
buttonView.axis = .vertical
buttonView.distribution = .fillEqually
buttonView.spacing = 20 // this is the spacing between each row of buttons
for _ in 0..<4 {
    var buttons = [UIButton]()
    for _ in 0..<3 {
        let numberButton = UIButton(type: .system)
        numberButton.setTitle("button", for: .normal)
        numberButton.titleLabel?.font = numberButton.titleLabel?.font.withSize(30)
        numberButton.setTitleColor(UIColor.black, for: .normal)
        // customise your button more if you want...
        buttons.append(numberButton)
    }
    let horizontalStackView = UIStackView(arrangedSubviews: buttons)
    horizontalStackView.alignment = .fill
    horizontalStackView.axis = .horizontal
    horizontalStackView.distribution = .fillEqually
    horizontalStackView.spacing = 20 // this is the spacing between each column of buttons
    buttonView.addArrangedSubview(horizontalStackView)
}

Result from playground quick look:

enter image description here

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Now I understood. First I should create vertical stackview, and add horizontal stackviews which contain buttons. I tried using stackview but couldn't think that I should create vertical stackview first. thank you – alphonse Jul 09 '20 at 05:10