نکات کلیدی
Dynamic Type — فناوری اپل است که به فونتهای برنامه اجازه میدهد هنگام تغییر اندازه سیستم متن، به طور خودکار مقیاسبندی شوند. کاربر اندازه ترجیحی خود را در Settings → Accessibility → Display & Text Size تنظیم میکند و همه برنامههایی که از Dynamic Type پشتیبانی میکنند، اندازه قلم را بدون راهاندازی مجدد تطبیق میدهند.
سیستم ۱۱ سطح مقیاسبندی ارائه میدهد: از XS (۱۴pt پایه) تا XXXL (۲۳pt پایه)، همچنین ۵ اندازه دسترسی اضافی (AX1–AX5) برای کاربران با اختلالات بینایی شدید. هنگام تغییر اندازه، iOS اعلان UIContentSizeCategory.didChangeNotification را تولید میکند و برنامه باید فونتها را از طریق UIFontMetrics دوباره بخواند. طبق Apple Human Interface Guidelines، Dynamic Type فاصله بین خطوط و نسبت حروف را تغییر نمیدهد — فقط اندازه قلم را تغییر میدهد که خوانایی را در همه اندازهها حفظ میکند.
Dynamic Type برای برنامههایی که به دنبال وضعیت دسترسپذیر (accessibility) هستند الزامی است. در WWDC 2024 اپل اعلام کرد که برنامههای بدون پشتیبانی از نوع پویا در معرض خطر رد شدن در بررسی هستند، اگر عملکرد اصلی آنها مربوط به خواندن متن باشد. در پروژههای IT Sectr ما Dynamic Type را از نسخه اول پیادهسازی میکنیم — این کار تا ۲۰٪ در زمان تطبیق بعدی برای دسترسپذیری صرفهجویی میکند.
اپل ۱۱ سبک متن از پیش تعریف شده را ارائه میدهد که هر کدام در UIFontDescriptor.UIAttributes برای فونت سیستمی SF Pro نمایش داده میشوند. توسعهدهنده اندازه پیکسلی را تعیین نمیکند — او سبک معنایی را انتخاب میکند و iOS بسته به تنظیمات کاربر، اندازه قلم مناسب را اعمال میکند.
| سبک | اندازه (پیشفرض) | اندازه (AX5) | کاربرد |
|---|---|---|---|
| .largeTitle | 34pt | 62pt | عنوانهای سطح اول صفحه |
| .title1 | 28pt | 50pt | عنوانهای فرعی |
| .title2 | 22pt | 40pt | عنوانهای بخش |
| .title3 | 20pt | 36pt | زیرعنوانها |
| .headline | 17pt semibold | 31pt | متن برجسته در لیستها |
| .body | 17pt | 31pt | متن اصلی |
| .callout | 16pt | 29pt | نکات و متن اضافی |
| .subheadline | 15pt | 27pt | شرح عناصر |
| .footnote | 13pt | 23pt | پاورقی و متن کوچک |
| .caption1 | 12pt | 21pt | شرح تصاویر |
| .caption2 | 11pt | 19pt | برچسبها و شرحهای کوچک |
هر سبک از فونت سیستمی SF Pro با ظاهر ثابت (Regular برای body، Bold برای headline) استفاده میکند. فونتهای سفارشی از طریق UIFontMetrics متصل میشوند — تنها راه صحیح تطبیق فونت شخص ثالث با نوع پویا.
UIFontMetrics — کلاسی است که در iOS 11 معرفی شد و هر UIFont دلخواه را متناسب با سبک متنی انتخاب شده مقیاسبندی میکند. قبل از iOS 11 توسعهدهندگان از فراخوانی مستقیم preferredFontForTextStyle استفاده میکردند که فقط فونت سیستمی SF Pro را برمیگرداند. UIFontMetrics این مشکل را حل میکند: هر فونتی را میپذیرد و نسخه مقیاسبندی شده آن را با حفظ ظاهر و تناسبات برمیگرداند.
متد scaledFont(for:) ضریب مقیاسبندی را بر اساس اندازه متن فعلی کاربر محاسبه میکند: اگر اندازه "بزرگ" (Large) انتخاب شده باشد، ضریب ۱.۰ است؛ اگر "بسیار بزرگ" (AX1) — تقریباً ۱.۳؛ برای "حداکثر" (AX5) — تا ۱.۸. ضریب به اندازه پایه فونت سفارشی اعمال میشود، نه به سیستم — این تضمین میکند که طراحی در همه اندازهها حفظ شود.
UIFontMetrics برای استفاده با همه فونتهای سفارشی در برنامه توصیه میشود. در WWDC 2024 اپل ابزار Accessibility Inspector را نشان داد که پشتیبانی از Dynamic Type را بررسی میکند و عناصری را که از اندازه ثابت به جای UIFontMetrics استفاده میکنند برجسته میکند. در IT Sectr ما UIFontMetrics را از سال ۲۰۱۸ در همه پروژهها پیادهسازی کردهایم — این کار تعداد باگهای همپوشانی متن را ۳۵٪ کاهش داده است.
سادهترین راه برای دریافت فونت پویا برای برچسب. کد نشان میدهد که چگونه یک UILabel با سبک .body تنظیم کنیم که به طور خودکار به تغییر اندازه سیستم متن واکنش نشان دهد.
import UIKit
class GreetingViewController: UIViewController {
private let label: UILabel = {
let l = UILabel()
l.text = "Hello, Dynamic Type!"
l.font = UIFont.preferredFont(forTextStyle: .body)
l.adjustsFontForContentSizeCategory = true
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
پرچم adjustsFontForContentSizeCategory = true به طور خودکار فونت را هنگام تغییر اندازه سیستم متن بهروزرسانی میکند — بدون این پرچم Dynamic Type برای برچسب موجود کار نخواهد کرد. هنگام تغییر اندازه، iOS layoutIfNeeded را فراخوانی میکند و label فونت را بدون دخالت دستی بهروزرسانی میکند.
هنگام استفاده از فونت سفارشی (مثلاً Montserrat)، فراخوانی preferredFontForTextStyle SF Pro را برمیگرداند، نه فونت شما. UIFontMetrics دقیقاً فونت سفارشی را مقیاسبندی میکند و طراحی آن را حفظ میکند.
import UIKit
extension UIFont {
static func customDynamicFont(name: String,
size: CGFloat,
style: UIFont.TextStyle) -> UIFont {
guard let baseFont = UIFont(name: name, size: size) else {
return .preferredFont(forTextStyle: style)
}
return UIFontMetrics(forTextStyle: style).scaledFont(for: baseFont)
}
}
let titleFont = UIFont.customDynamicFont(
name: "Montserrat-Bold",
size: 20,
style: .title3
)
متد scaledFont(for:) یک UIFont پایه میپذیرد و نسخه مقیاسبندی شده متناسب با سبک .title3 را برمیگرداند. در اندازه دسترسی AX5، فونت Montserrat-Bold 20pt به ~36pt تبدیل میشود — دقیقاً به همان اندازه که فونت سیستمی این سبک افزایش مییابد. در IT Sectr ما از این الگو در همه پروژههای دارای فونت سفارشی از سال ۲۰۱۸ استفاده میکنیم که شکایات مربوط به متن کوچک را از کاربران دارای محدودیت بینایی کاملاً حذف کرده است.
اگر فونت را به صورت دستی بهروزرسانی میکنید (بدون adjustsFontForContentSizeCategory)، در اعلان UIContentSizeCategory.didChangeNotification مشترک شوید. این برای عناصر UI سفارشی که بهروزرسانی خودکار فونت را به ارث نمیبرند ضروری است.
import UIKit
class DynamicLabel: UILabel {
private var customFont: UIFont?
private var textStyle: UIFont.TextStyle = .body
func configure(font: UIFont, style: UIFont.TextStyle) {
customFont = font
textStyle = style
NotificationCenter.default.addObserver(
self,
selector: #selector(updateFont),
name: UIContentSizeCategory.didChangeNotification,
object: nil
)
updateFont()
}
@objc private func updateFont() {
guard let base = customFont else { return }
self.font = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: base)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
اشتراک در didChangeNotification تضمین میکند که عنصر سفارشی فونت را در هر تغییری در تنظیمات سیستم بدون راهاندازی مجدد برنامه بهروزرسانی کند. از iOS 15 به بعد، اعلان حتی هنگام تغییر اندازه متن از طریق Control Center در برنامههای پشتیبانیکننده از Live Text Size نیز ارسال میشود.
سوالات متداول
Dynamic Type در iOS 7 و جدیدتر در دسترس است. UIFontMetrics در iOS 11 معرفی شد — قبل از آن مستقیماً از متد preferredFontForTextStyle استفاده میشد. در iOS 15+ نوع پویا از اندازههای دسترسی اضافی (AX1–AX5) برای فونتهای بزرگ پشتیبانی میکند. برنامههایی که از iOS 10 و پایینتر پشتیبانی میکنند از preferredFontForTextStyle بدون UIFontMetrics استفاده میکنند که پشتیبانی را فقط به فونت سیستمی SF Pro محدود میکند.
در Xcode 15+ شبیهساز را باز کنید و Settings → Accessibility → Display & Text Size → Larger Text را انتخاب کنید. اسلایدر را برای تغییر اندازه بکشید. در خود Xcode گزینه Debug → Accessibility Inspector وجود دارد که عناصر با فونت ثابت را برجسته میکند. برای خودکارسازی از تستی استفاده کنید که UISlider تنظیمات را از طریق XCUITest تغییر میدهد — این تضمین میکند که همه صفحهها به درستی بازسازی میشوند.
بله، Auto Layout با نوع پویا نیاز به استفاده از intrinsicContentSize در UILabel و UIButton دارد. در اندازههای دسترسی، متن ممکن است از مرزهای superview خارج شود — UIScrollView اضافه کنید یا محدودیتهای leading/trailing را افزایش دهید. برای فاصلهها (padding) از UIFontMetrics.scaledValue استفاده کنید تا فاصله بین حروف نیز متناسب با فونت مقیاسبندی شود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.