Make font grow together with UILabel (resized by Auto Layout) - how to do it in Interface Builder?
Asked Answered
B

6

24

In a simple iPhone app I display a letter tile (custom UIView with an image and 2 labels) by the following code in viewDidLoad:

app screenshot

DraggedTile *tile = [[[NSBundle mainBundle] loadNibNamed:@"DraggedTile"
                                                   owner:self
                                                 options:nil] firstObject];
tile.frame = CGRectMake(10 + arc4random_uniform(100),
                        10 + arc4random_uniform(100),
                        kWidth,
                        kHeight);
[self.view addSubview:tile];

This works okay, but I would like to make the letter tile grow - when I supply bigger width and height parameters to the CGRectMake.

So in Xcode 5.1 Interface Builder I open the DraggedTile.xib and enable "Auto Layout".

Then for the image and letter I add constraints to the left, top, right, bottom edges of the parent.

For the letter label I also set "Lines" to 0 and "Content Compression Resistance Priority" to 1000 (here fullscreen 1 and fullscreen 2):

Xcode screenshot

Xcode screenshot

Then I modify the code to use bigger width and height:

tile.frame = CGRectMake(10 + arc4random_uniform(100),
                        10 + arc4random_uniform(100),
                        2 * kWidth,
                        2 * kHeight);

Here is the result:

app screenshot

Both the background image and the letter label seem to have grown as intended.

However the font size of the label hasn't grown.

I've searched around and I think that I need something like tile.letter.adjustsFontSizeToFitWidth = YES. But at the same time I can not use it with "Auto Layout" being on...

So my question is if there is any option in the "Interface Builder" available to make the font size grow as well?

UPDATE:

I've tried ismailgulek's suggestion to set the font size to 200 in Interface Builder and in the code tile.letter.adjustsFontSizeToFitWidth = YES and it looks promising (here fullscreen):

Xcode screenshot

but I have now the problem that I have set 40px as the letter.bottom constraint in Interface Builder. But what if I need a bigger tile frame? Is there a way to use percentage instead of absolute pixel value in that constraint?

And another question is if it's possible to set the adjustsFontSizeToFitWidth somewhere in the Interface Builder or do I have to use source code for that? I've tried adding a key to the "User Defined Runtime Attributes" - but then the app crashes at the runtime:

Xcode screenshot

Bac answered 27/3, 2014 at 13:16 Comment(5)
You are supposed to set constraints for the other label too.Ninefold
but your other label seems to look misplaced,do you want it that way?Ninefold
I will correct the position of the other label later. Now I am asking about the font size.Bac
What sizes are you looking at? If you rasterize the layer of the label with at a large scale, you could achieve this effect very easily with little work.Tubercle
Actually I've solved my problem in the meantime by resizing all graphical assets. But thanks for the advice.Bac
L
27

adjustsFontSizeToFitWidth property of UILabel will not grow up the font size, it is only for reducing according to the documentation: Normally, the label text is drawn with the font you specify in the font property. If this property is set to YES, however, and the text in the text property exceeds the label’s bounding rectangle, the receiver starts reducing the font size until the string fits or the minimum font size is reached.

But if you set font size big enough (say 200) and set adjustsFontSizeToFitWidth to YES, i think you would get interestingly valuable results.

And do not forget to set Baseline as Align Centers, otherwise your text may not be seen properly.

Please inform us about your results.

Lietuva answered 28/3, 2014 at 0:19 Comment(1)
This is what I have been doing which created way too much space above the text on smaller screens. However, I totally skipped over the Align centers which, as you described, did help with my issue since I'm only doing this with the title. Thanks!Eyeshade
A
14

For those who come here by the title and need a simple solution (after hours of investigations):

Problem example: If you use auto layout and set the UILabel height to be proportional to the screen height, you will get a frame which is low for iPhone (landscape) and high for iPad. How to adjust font height automatically?

Solution: in Interface Builder,

  1. Set "Autoshrink" to "Minimum font size" and set something for the size (it affects too-wide texts, but required for our solution).
  2. Set "Lines" to be 0, and make font size higher than the frame you will get in iPad.

This will cause the font to get increased automatically to the current height.

Augustina answered 2/2, 2016 at 3:19 Comment(1)
Thanks! Setting lines to 0 was the missing piece to make it scale as needed. I didn't understand why this wasn't working.Donal
L
2

You can accomplish what you want by setting Autoshrink in your storyboard. It will cause the label to shrink to a minimum scale/explicit size when the screen size gets smaller. Make it work on the biggest screen size and then ensure it shrinks to the size you want in the storyboard preview.

Lianna answered 5/5, 2015 at 19:11 Comment(0)
H
1

You can replace the class in Interface Builder with your own derived class and do resizing there.

Example:

/**
MYLabel does exactly the same like UILabel, except that the font size will automatically shrink 
if the code is executed on an iPhone.
*/

class MYLabel: UILabel {

    var onlyOnceToken: dispatch_once_t = 0

    override func drawRect(rect: CGRect) {

        dispatch_once(&onlyOnceToken) {

            if let usedFont:UIFont = self.font {

                // define your reference size here
                let iPadHeight:CGFloat = 768
                let screenBounds = UIScreen.mainScreen().bounds
                let scale:CGFloat =  screenBounds.height / iPadHeight
                self.font = UIFont(name: usedFont.fontName, size: CGFloat(usedFont.pointSize) * scale)
            }
        }

        super.drawRect(rect)
    }
}

From now on you just need to replace the UILabel class with MYLabel in the identity inspector of IB and all your fonts automatically resize proportionally to your devices height.

If you want to just grow it together with the label size, replace

let screenBounds = UIScreen.mainScreen().bounds

with

let screenBounds = self.bounds.height

or any other custom scale formula. UIFont offers you additional measurement properties you can do a lot with this approach.

Hypervitaminosis answered 11/6, 2015 at 10:7 Comment(0)
R
1

Also make sure you set “Line Breaks” from “Word Wrap” to “Truncate Tail.”

Radionuclide answered 23/4, 2020 at 23:29 Comment(0)
I
0

The font will not grow automatically.
You should increase/decrease it by yourself, in IB or programmatically.

Imperil answered 27/3, 2014 at 19:54 Comment(1)
This is not true. see my answer below.Augustina

© 2022 - 2024 — McMap. All rights reserved.