How to detect Dynamic Font size changes from iOS Settings?
Asked Answered
I

3

65

Inside settings->general->text size, after changing the text size, I'd have to exit my own app to have the sizes applied to

 [UIFont preferredFontForTextStyle:..]

Is there a delegate or notification to notify my app to re-apply the new sizes?

Update: I tried the following but interestingly, the font size will apply after I BG and launch the app TWICE.

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fromBg:) name:UIApplicationDidBecomeActiveNotification object:nil];

}


 -(void) fromBg:(NSNotification *)noti{

    self.headline1.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
    self.subHeadline.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
    self.body.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    self.footnote.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
    self.caption1.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1];
    self.caption2.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2];
//    [self.view layoutIfNeeded];

}
Interdict answered 23/9, 2013 at 3:23 Comment(0)
C
64

You listen for the Size Change Notification on UIContentSizeCategory.

Swift 3.0: NSNotification.Name.UIContentSizeCategoryDidChange

Swift 4.0 or later: UIContentSizeCategory.didChangeNotification

Cy answered 23/9, 2013 at 3:28 Comment(3)
Ok but what do I do to apply the new font sizes? Do I set the fonts to the preferredFontForTextStyle again?Interdict
@Interdict yep, that's all you need to do.Cy
Have issues in Swift 4.2 with adjustsFontForContentSizeCategory not working, the notification always works.Dentilabial
D
74

With Swift 5 and iOS 12, you can choose one of the three following solutions in order to solve your problem.


#1. Using UIContentSizeCategoryAdjusting's adjustsFontForContentSizeCategory property

UILabel, UITextField and UITextView conform to UIContentSizeCategoryAdjusting protocol and therefore have an instance property called adjustsFontForContentSizeCategory. adjustsFontForContentSizeCategory has the following declaration:

A Boolean value indicating whether the object automatically updates its font when the device's content size category changes.

var adjustsFontForContentSizeCategory: Bool { get set }

The UIViewController implementation below shows how to detect and react to dynamic font size changes in iOS settings with adjustsFontForContentSizeCategory:

import UIKit

class ViewController: UIViewController {

    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        label.numberOfLines = 0
        label.font = .preferredFont(forTextStyle: UIFont.TextStyle.body)
        label.adjustsFontForContentSizeCategory = true
        view.addSubview(label)

        // Auto layout
        label.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = label.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        let widthConstraint = label.widthAnchor.constraint(equalToConstant: 300)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint])
    }

}

#2. Using UIContentSizeCategory's didChangeNotification type property

UIContentSizeCategory has a type property called didChangeNotification. didChangeNotification has the following declaration:

Posted when the user changes the preferred content size setting.

static let didChangeNotification: NSNotification.Name

This notification is sent when the value in the preferredContentSizeCategory property changes. The userInfo dictionary of the notification contains the newValueUserInfoKey key, which reflects the new setting.

The UIViewController implementation below shows how to detect and react to dynamic font size changes in iOS settings with didChangeNotification:

import UIKit

class ViewController: UIViewController {

    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        label.numberOfLines = 0
        label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
        view.addSubview(label)

        // Register for `UIContentSizeCategory.didChangeNotification`
        NotificationCenter.default.addObserver(self, selector: #selector(preferredContentSizeChanged(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)

        // Auto layout
        label.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = label.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        let widthConstraint = label.widthAnchor.constraint(equalToConstant: 300)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint])
    }

    @objc func preferredContentSizeChanged(_ notification: Notification) {
        label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
        /* perform other operations if necessary */
    }

}

#3. Using UITraitCollection's preferredContentSizeCategory property

UITraitCollection has a property called preferredContentSizeCategory. preferredContentSizeCategory has the following declaration:

The font sizing option preferred by the user.

var preferredContentSizeCategory: UIContentSizeCategory { get }

With Dynamic Type, users can ask that apps display text using fonts that are larger or smaller than the normal font size defined by the system. For example, a user with a visual impairment might request a larger default font size to make it easier to read text. Use the value of this property to request a UIFont object that matches the user's requested size.

The UIViewController implementation below shows how to detect and react to dynamic font size changes in iOS settings with preferredContentSizeCategory:

import UIKit

class ViewController: UIViewController {

    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        label.numberOfLines = 0
        label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
        view.addSubview(label)

        // Auto layout
        label.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = label.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        let widthConstraint = label.widthAnchor.constraint(equalToConstant: 300)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint])
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory {
            self.label.font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
            /* perform other operations if necessary */
        }
    }

}

Sources:

Demivolt answered 6/8, 2017 at 20:50 Comment(2)
Thanks for the detailed answer! I couldn't find if there was a way to programmatically detect Larger Accessibility Sizes switch is turned on or off. Do you know if it can be done?Colima
@Colima You can test it like that: if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { /* ... */ }. See useyourloaf.com / Making Space For Dynamic Type for more details.Demivolt
C
64

You listen for the Size Change Notification on UIContentSizeCategory.

Swift 3.0: NSNotification.Name.UIContentSizeCategoryDidChange

Swift 4.0 or later: UIContentSizeCategory.didChangeNotification

Cy answered 23/9, 2013 at 3:28 Comment(3)
Ok but what do I do to apply the new font sizes? Do I set the fonts to the preferredFontForTextStyle again?Interdict
@Interdict yep, that's all you need to do.Cy
Have issues in Swift 4.2 with adjustsFontForContentSizeCategory not working, the notification always works.Dentilabial
B
0

Adding on to Imanou Petit 's Answer

You can also do this to get the size:

let contentSize = traitCollection.preferredContentSizeCategory
if contentSize.isAccessibilityCategory {
   if contentSize >= .accessibilityLarge{
        print("larger than or equal to accessibility large")
    }else {
        print("lower than large")
    }
} else {

    print("not accessibility")
}

}

Bandler answered 9/3, 2022 at 16:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.