1
votes

I have square buttons whose size vary whether it's displayed on an iPad or iPhone. I want the font of the buttons title to adjust to the size of the buttons, ie. so that they don't look too small on the bigger iPad screen, or too big on a smaller iPhone screen.

I came up with the following solution :

// Buttons is an outlet collection
for button in Buttons {
            button.titleLabel?.adjustsFontSizeToFitWidth = true
            button.titleEdgeInsets = UIEdgeInsetsMake(button.frame.height/3, button.frame.width/3, button.frame.height/3, button.frame.width/3)
            button.titleLabel!.numberOfLines = 1
            button.titleLabel!.minimumScaleFactor = 0.1
            button.clipsToBounds = true
            button.titleLabel?.baselineAdjustment = UIBaselineAdjustment.alignCenters

            print(button.titleLabel!.font.pointSize)


        }

This provides an adjustment of the size of the font based on the width of the title. So buttons with a shorter title will have a bigger font than buttons with a longer title.

I want the same font size for all buttons, so I would like to access the adjusted size of one of them (let's say the smallest) to set it to all buttons. How could I do that ?

Alternatively I was thinking to adjust the font to the button height and not width but couldn't find a solution that worked.

3
please check the answer and reply - Mr. Xcoder
See the updated answer, now working for any value - Mr. Xcoder
I had this problem early on in my iOS developing journey, but I've now come to realize that this is not a good way to design an app. The reason why it is not easy to do this is because really your content should not be "growing" on a larger screen, but instead you change the app to show more content. Just a thought, but I've found it to be a much better way to develop apps. - Benjamin Lowry
Should accept the answer if it helped - Mr. Xcoder

3 Answers

2
votes

Here is my solution in swift 4:

private func adjustedFontSizeOf(label: UILabel) -> CGFloat {
    guard let textSize = label.text?.size(withAttributes: [.font: label.font]), textSize.width > label.bounds.width else {
        return label.font.pointSize
    }

    let scale = label.bounds.width / textSize.width
    let actualFontSize = scale * label.font.pointSize

    return actualFontSize
}

Hope it helps someone.

1
votes

This worked for me with Swift 5, I hope it helps.

func adjustedFontSizeOf(label: UILabel, sizeBounds: CGSize) -> CGFloat {
    
    // return the real pointSize for a label with adjustsFontSizeToFitWidth activated
    // sizeBounds is the frame size where the label is enclosed (UIButton frame or similar)
    // because label.frame or label.bounds is always CGRect.zero
    
    let textSize = label.intrinsicContentSize
    
    var actualFontSize = label.font.pointSize
    if textSize.width > sizeBounds.width { // otherwise is not adjusted
        let scale = sizeBounds.width / textSize.width
        actualFontSize = scale * label.font.pointSize
    }

    return actualFontSize
}

func setButtonsToTheSameFontSize(buttons: [UIButton], maxPointSize: CGFloat)
{
    // set a list of buttons whose titleLabels have adjustFontSizeToFitWidth activated
    // to the same font pointSize using the minimum size among them
    
    var fsize: CGFloat = maxPointSize
    for b in buttons {
        let f = adjustedFontSizeOf(label: b.titleLabel!, sizeBounds: b.frame.size)
        if f < fsize { fsize = f }
    }
    for b in buttons { b.titleLabel?.font = b.titleLabel?.font.withSize(fsize) }
}
0
votes

This is a solution for setting the font size of all the buttons to minimum size(amongst them).

Step 1. I have initialised some new buttons, for testing:

let button = UIButton()
button.titleLabel!.font =  UIFont(name: "Helvetica", size: 20)
let button2 = UIButton()
button2.titleLabel!.font = UIFont(name: "Helvetica", size: 16)
let button3 = UIButton()
button3.titleLabel!.font = UIFont(name: "Helvetica", size: 19)
let Buttons = [button, button2, button3]

Step 2. Then, I have added a variable called min and I have initialised it with a value bigger than nearly any possible button font size, 100, like so:

var min = CGFloat(Int.max)

Step 3. After that, I have added some more code to your loop:

for btn in Buttons{
  // here goes your code for your buttons(the code from the question)
  // then my code:
    if (btn.titleLabel?.font.pointSize)! < min{
        min = (btn.titleLabel?.font.pointSize)! // to get the minimum font size of any of the buttons 
    }
}

print(min) // prints 16, which is correct amongst the value [20,19,16] 

so your code will look like this:

for btn in Buttons{
    btn.titleLabel?.adjustsFontSizeToFitWidth = true
    btn.titleEdgeInsets = UIEdgeInsetsMake(btn.frame.height/3, btn.frame.width/3, btn.frame.height/3, btn.frame.width/3)
    btn.titleLabel!.numberOfLines = 1
    btn.titleLabel!.minimumScaleFactor = 0.1
    btn.clipsToBounds = true
    btn.titleLabel?.baselineAdjustment = UIBaselineAdjustment.alignCenters
    print(btn.titleLabel!.font.pointSize)
    if (btn.titleLabel?.font.pointSize)! < min{
          min = (btn.titleLabel?.font.pointSize)! // to get the minimum font size of any of the buttons 
     }    
}

Step 4. Setting the font size of all the buttons to min:

Buttons.map { $0.titleLabel?.font = UIFont(name:($0.titleLabel?.font.fontName)! , size: min) }

or

for btn in Buttons{
    btn.titleLabel?.font = UIFont(name: (btn.titleLabel?.font.fontName)!, size: min)
}

If your minimum font size is, let's say... 15, then the font size of all the buttons will become 15.


And that's it. Hope it helps!