如何检测iOS设置中动态字体大小的更改?

64

在设置->通用->文本大小中,修改文本大小后,我必须退出我的应用程序才能应用更改。

 [UIFont preferredFontForTextStyle:..]

是否有委托或通知可以通知我的应用程序重新应用新的尺寸?

更新:我尝试了以下操作,但有趣的是,在我两次后台运行和启动应用程序后,字体大小才会应用。

- (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];

}
3个回答

73

使用 Swift 5 和 iOS 12,您可以选择以下三种解决方案之一来解决问题。


#1. 使用 UIContentSizeCategoryAdjustingadjustsFontForContentSizeCategory 属性

UILabelUITextFieldUITextView 符合 UIContentSizeCategoryAdjusting 协议,因此具有名为adjustsFontForContentSizeCategory的实例属性。adjustsFontForContentSizeCategory 的声明如下:

一个布尔值,指示对象在设备的内容大小类别更改时是否自动更新其字体。

var adjustsFontForContentSizeCategory: Bool { get set }
下面的 UIViewController 实现展示了如何利用 adjustsFontForContentSizeCategory 检测并响应 iOS 设置中动态字体大小的变化:
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. 使用UIContentSizeCategorydidChangeNotification类型属性

UIContentSizeCategory有一个名为didChangeNotification的类型属性。 didChangeNotification声明如下:

当用户更改首选内容大小设置时发布。

static let didChangeNotification: NSNotification.Name

preferredContentSizeCategory属性的值改变时,将发送此通知。通知的userInfo字典包含newValueUserInfoKey键,该键反映了新的设置。

下面的UIViewController实现展示了如何使用didChangeNotification检测并响应iOS设置中的动态字体大小更改:

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. 使用UITraitCollectionpreferredContentSizeCategory属性

UITraitCollection有一个叫做preferredContentSizeCategory的属性。该属性声明如下:

用户偏好的字体大小选项。

var preferredContentSizeCategory: UIContentSizeCategory { get }
使用动态类型,用户可以请求应用程序使用比系统定义的正常字体大小更大或更小的字体显示文本。例如,视力障碍的用户可能会要求更大的默认字体大小,以便更容易地阅读文本。使用此属性的值来请求与用户所需大小匹配的UIFont对象。下面的UIViewController实现展示了如何检测并响应iOS设置中首选内容大小类别的动态字体大小更改:
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 */
        }
    }

}

资料来源:


1
感谢详细的回答!我找不到一种方法来编程检测较大的辅助功能尺寸开关是否已打开或关闭。您知道能否实现吗? - Dave
5
你可以像这样测试它:if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { /* ... */ }。更多细节请参阅 useyourloaf.com / Making Space For Dynamic Type - Imanou Petit

64
你可以监听 UIContentSizeCategory 上的“尺寸更改通知”。 Swift 3.0: 使用NSNotification.Name.UIContentSizeCategoryDidChangeSwift 4.0 或更新版本: 使用UIContentSizeCategory.didChangeNotification

2
好的,但是我该怎么做才能应用新的字体大小呢?我需要再次将字体设置为preferredFontForTextStyle吗? - mskw
@mskw 是的,这就是你需要做的全部。 - Dave DeLong
在Swift 4.2中,adjustsFontForContentSizeCategory无法正常工作,通知始终起作用。 - Brett

0

Imanou Petit答案上进行补充:

你也可以这样做来获取大小:

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")
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接