Search code examples
iosswiftautolayoutscalinguicomponents

How to scale the button text based on screen design swift?


In my project, i am using scaling for UI components. I am able to scale the text for UIlabel like below and it's working in all device:

1. Autoshrinks - minimum font scale set it to 0.5

2. No of lines - 0

3. Enable dynamic type in attribute inspector

4. adjustFontSizeToWidth to true

But when i am trying to adjust font for UI Button using beolow steps and i am not able to scale the text for UI button.

button.titleLabel?.numberOfLines = 1 // Tried with 0 also

button.titleLabel?.adjustsFontSizeToFitWidth = true

button.titleLabel?.lineBreakMode = // tried differenet linebreakmode

Could anyone have an idea of scaling UI Button text?


Solution

  • Are you sure it's not working?

    Edit - After comments...

    UIKit elements such as UILabel / UIButton / etc to not have a built-in "auto-adjust font height" property.

    I don't work for Apple, so just guessing that is (at least in part) due to the fact that, in general...

    Based on screen height, the UI is designed to either:

    • provide more or less information, e.g. more rows in a table, or
    • adjust vertical spacing between elements

    That doesn't mean you can't or shouldn't adjust your font sizes... it just means you have to do it manually.

    Couple options:

    • set the font-size at run-time, as suggested by Duncan
    • use a UIAppearance proxy to set the font-size, again at run-time

    in either case, you could use a height-to-fontSize table or a "percentage" calculation.

    Another option would be a custom class that sets the font-size based on the constrained button height.

    Here's a simple example (note: for demonstration purposes only):

    class AutoFontSizeButton: UIButton {
        
        override func layoutSubviews() {
    
            super.layoutSubviews()
    
            guard let fnt = titleLabel?.font else { return }
    
            // default system type button has 6-pts top / bottom inset
            //  and font size is 15/18ths of that height
            let h = ((bounds.height - 12.0) * (15.0 / 18.0)).rounded()
            let fs = fnt.pointSize
    
            if h != fs {
                titleLabel?.font = UIFont(descriptor: fnt.fontDescriptor, size: h)
            }
    
        }
    
    }
    

    Result - the top three (yellow) buttons are 30, 40 and 50-points in height, with the default font-size of 15. The bottom three (green) buttons are again 30, 40 and 50-points in height, but the font-size is automatically set at run-time:

    enter image description here