Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize views after dynamic type's UIContentSizeCategoryDidChangeNotification

I want to embrace dynamic type in my app, and I want it to be responsive to text size changes while it's running, without restarting the app (when I restart, it applies the new size successfully).

I've implemented UIContentSizeCategoryDidChangeNotification in my app delegate, and fired a notification on applicationDidBecomeActive:, notifying my view controllers. In my view controller's handler method, I've tried:

  • [self.view setNeedsDisplay];
  • [self.view setNeedsLayout];
  • [self.view invalidateIntrinsicContentSize];

But none seem to work. It does nothing. It is called (hits the breakpoint) when app becomes active, and it does get called for the frontmost view, but nothing changes.

How can I make my app respond to type changes dynamically when running?

like image 353
Can Poyrazoğlu Avatar asked Jan 07 '23 13:01

Can Poyrazoğlu


2 Answers

First, your UIViewControllers need to observe the UIContentSizeCategoryDidChangeNotification notification (which you are). As documentation, I'll leave an example:

- (void)viewWillAppear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(contentSizeCategoryDidChangeNotification:)
                                                 name:UIContentSizeCategoryDidChangeNotification
                                               object:nil];
}

Next, we'll define our selector, contentSizeCategoryDidChangeNotification:. This function is where we need to explicitly update each UI element (for UILabel, UIButton, etc.). Simply triggering a layout pass will not do this.

For example, say you have a label and button:

- (void)contentSizeCategoryDidChangeNotification {

    // Updating a UILabel's size for a given text style:
    self.headlineLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];

    // Similarly, updating a UIButton's size for a given style:
    [self.button.titleLabel setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];

    ...
}

+ (UIFont)preferredFontForTextStyle: will return the correctly sized UIFont for a given text style, adjusted for the system Dynamic Type content size (which range from XS to XXXL).

Finally, remember to remove yourself as an observer:

[[NSNotificationCenter defaultCenter] removeObserver:self];

Hope this helps!

like image 58
Janum Trivedi Avatar answered Jan 19 '23 00:01

Janum Trivedi


In iOS 10+, the adjustsFontForContentSizeCategorynow exists. Set this to YES on your Labels and it will auto-update the font size, assuming your font is set to use Text Style font.

You can also set this from IB with the "Automatically Adjusts Font" checkbox. Note that this checkbox has no impact if it is not paired with a Text Style font (such as Body, Headline, Subhead, etc.).

enter image description here

like image 43
Fostah Avatar answered Jan 19 '23 00:01

Fostah