How to detect Dynamic Font size changes from iOS Settings?
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];
}
Solution 1:
You listen for the Size Change Notification on UIContentSizeCategory.
Swift 3.0:
NSNotification.Name.UIContentSizeCategoryDidChange
Swift 4.0 or later:
UIContentSizeCategory.didChangeNotification
Solution 2:
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 thenewValueUserInfoKey
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:
- useyourloaf.com / Auto Adjusting Fonts for Dynamic Type