0

I have two buttons in a vertical stack view with the exact same title, font and font size. They should thus have the same intrinsic size along the vertical direction and UIStackView.Distribution.fillProportionally should give them both the same height but when I check their respective frames in the size inspector one button's height is larger than the other's, why? UIStackView.Distribution.fillProportionally One buttons height is 94 while the other's is 86. Fill equally works as expected however.enter image description here enter image description here

I printed the frames' heights and they come out the same as in the storyboard 94 and 86 which don't match.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    print("button 1 height: \(button1.frame.height)")
    print("button 2 height: \(button2.frame.height)")
  }

Terminal output

button 1 height: 94.0
button 2 height: 86.0
button 1 height: 94.0
button 2 height: 86.0

Code to reproduce the situation

import UIKit

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    var buttonOne = UIButton()
    
    buttonOne.titleLabel?.font = UIFont(name: "Marker Felt Wide", size: 17.0)
      buttonOne.backgroundColor = .red
    buttonOne.setTitle("Pirate Handbook", for: [])
    var buttonTwo = UIButton()
    
    buttonTwo.titleLabel?.font = UIFont(name: "Marker Felt Wide", size: 17.0)
      buttonTwo.backgroundColor = .blue
    
    buttonTwo.setTitle("Pirate Handbook", for: [])
    
    buttonTwo.translatesAutoresizingMaskIntoConstraints = false
    buttonOne.translatesAutoresizingMaskIntoConstraints = false
    var stackView = UIStackView()
    stackView.axis = .vertical
    
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.distribution = .fillProportionally
    stackView.alignment = .fill
    
    
    stackView.addArrangedSubview(buttonTwo)
    stackView.addArrangedSubview(buttonOne)
    stackView.backgroundColor = .green
    
    view.addSubview(stackView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.distribution = .fillProportionally
    stackView.alignment = .fill
    stackView.spacing = 8
    
    NSLayoutConstraint.activate([
        stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 110),
        stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 23),
        stackView.widthAnchor.constraint(equalToConstant: 154),
        stackView.heightAnchor.constraint(equalToConstant: 188)
    ])
    
    
  }

  override func viewDidLayoutSubviews() {
    var views = view.subviews.first?.subviews
    views?.forEach{
      print($0.frame.height)
    }
  }

}

Terminal output when I created the views in code as opposed to storyboard

> height 0.0 
> height 0.0
> height 84.33333333333333
> height 95.66666666666667

I am using a standard spacing of 8.0 points both in the storyboard and in the code. When I make the spacing in the stack view 0 points it works as expected with both buttons having an equal height of 94.0

iosdev
  • 53
  • 8
  • It looks like the buttons have different content insets. Did you set the content insets to different values perhaps? – Sweeper Jul 09 '23 at 05:07
  • @Sweeper both have the same exact content insets - 15 left and 15 right, the top and bottom insets are both 0 – iosdev Jul 09 '23 at 05:09
  • After a bit of trial and error in the storyboard, I was able to reproduce. If anything, this seems like a storyboard bug. When you run the app, it works correctly. – Sweeper Jul 09 '23 at 05:12
  • Removing and re-adding some constraints, so that the storyboard tries to layout again, fixes the problem in the storyboard for me. – Sweeper Jul 09 '23 at 05:17
  • @Sweeper I printed out the frames in viewDidLayoutSubviews() and they have different heights 94 and 86 same as the storyboard. Is this the right function to override to check the frames after layout? Also I deleted and re-added all the constraints but it doesn't fix it in the storyboard for me. – iosdev Jul 09 '23 at 05:25
  • Okay, you need to post a [mcve] then I’m afraid. Include all the steps to reproduce the problem, starting from “create a new project”. – Sweeper Jul 09 '23 at 05:38
  • Is the spacing between buttons intended? If yes, how did you set it? – oneshot Jul 09 '23 at 06:33
  • For the lower button, under View, try to change its frame origin y from 102 to a lower value and play a bit with it. – oneshot Jul 09 '23 at 06:43
  • @oneshot I am using standard spacing in both IB and code which is 8.0 points. So no matter how i build the views - code or IB the same thing happens. – iosdev Jul 09 '23 at 06:47
  • @Sweeper I uploaded a code sample to reproduce the situation. – iosdev Jul 09 '23 at 06:47
  • 1
    https://stackoverflow.com/questions/46253248/uistackview-proportional-layout-with-only-intrinsiccontentsize I guess this question and its related answer explain why. Probably it's safer to just use .fillEqually – oneshot Jul 09 '23 at 07:06
  • `.fillProportionally` ***does not work correctly*** when the stack view has spacing greater than **Zero**. In your case, you would not want to use proportional fill anyway. – DonMag Jul 09 '23 at 13:04

0 Answers0