You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

系统字体大小变更时如何获取UIButton的最新尺寸?

解决动态字体大小变更后立即获取UIButton更新宽度的问题

当系统字体大小变更时,UIContentSizeCategory.didChangeNotification会立即触发,但此时UIKit尚未完成控件的布局更新,直接读取button.frame.width得到的还是旧值。你可以通过以下两种方式获取更新后的宽度:

方法1:强制触发布局更新后读取frame

在通知处理器中调用控件的layoutIfNeeded()方法,强制UIKit立即完成布局计算,之后就能获取到最新的frame宽度。注意必须在主线程执行UI操作:

@objc func handleFontSizeChange(_ notification: Notification) {
    DispatchQueue.main.async {
        // 强制按钮完成布局更新
        self.acceptButton.layoutIfNeeded()
        self.cancelButton.layoutIfNeeded()
        
        let acceptWidth = self.acceptButton.frame.width
        let cancelWidth = self.cancelButton.frame.width
        
        // 计算总宽度(包含按钮间距)
        let totalRequiredWidth = acceptWidth + cancelWidth + 20 // 20为按钮间的水平间距
        let dialogWidth = self.dialogView.bounds.width
        
        // 根据空间切换布局
        self.buttonStackView.axis = totalRequiredWidth > dialogWidth ? .vertical : .horizontal
        self.buttonStackView.layoutIfNeeded()
    }
}

方法2:直接读取控件的固有内容大小

UIButton的intrinsicContentSize会在字体变更后立即更新,这个值包含了按钮标题、内边距等因素决定的固有宽度,无需等待布局完成即可获取:

@objc func handleFontSizeChange(_ notification: Notification) {
    DispatchQueue.main.async {
        let acceptIntrinsicWidth = self.acceptButton.intrinsicContentSize.width
        let cancelIntrinsicWidth = self.cancelButton.intrinsicContentSize.width
        
        let totalRequiredWidth = acceptIntrinsicWidth + cancelIntrinsicWidth + 20
        let dialogWidth = self.dialogView.bounds.width
        
        self.buttonStackView.axis = totalRequiredWidth > dialogWidth ? .vertical : .horizontal
        self.buttonStackView.layoutIfNeeded()
    }
}

注意事项

  • 注册通知时要确保在主线程,并且在视图销毁时移除通知:
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(handleFontSizeChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}
  • 如果使用UIStackView管理按钮,确保stackView的约束设置正确,比如给stackView设置水平方向的约束,让它的宽度受限于对话框的宽度,这样切换axis后布局能自动适配。

内容的提问来源于stack exchange,提问作者Mapleman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:25:09