النقاط الرئيسية
Dynamic Type هي تقنية من Apple تسمح بتحجيم خطوط التطبيق تلقائيًا عند تغيير حجم نص النظام. يحدد المستخدم الحجم المفضل لديه في الإعدادات → إمكانية الوصول → العرض وحجم النص، وجميع التطبيقات التي تدعم Dynamic Type تكيّف حجم الخط دون إعادة تشغيل.
يوفر النظام 11 مستوى تحجيم: من XS (14pt أساسي) إلى XXXL (23pt أساسي)، بالإضافة إلى 5 أحجام إضافية لإمكانية الوصول (AX1–AX5) للمستخدمين ذوي الإعاقات البصرية الشديدة. عند تغيير الحجم، يُنشئ iOS إشعار UIContentSizeCategory.didChangeNotification، ويجب على التطبيق إعادة تحميل الخطوط عبر UIFontMetrics. وفقًا لإرشادات واجهة المستخدم من Apple، لا يغير Dynamic Type تباعد الأسطر أو نسب الحروف — فقط حجم الخط، مما يحافظ على readability في جميع الأحجام.
Dynamic Type إلزامي للتطبيقات التي تسعى للحصول على حالة إمكانية الوصول. في WWDC 2024، أعلنت Apple أن التطبيقات بدون دعم النوع الديناميكي تخاطر بالرفض أثناء المراجعة إذا كانت وظيفتها الأساسية تتعلق بقراءة النص. في مشاريع IT Sectr، نقوم بتطبيق Dynamic Type من الإصدار الأول — مما يوفر ما يصل إلى 20% من الوقت في التكيف اللاحق مع إمكانية الوصول.
توفر Apple 11 نمط نص محدد مسبقًا، يتم عرض كل منها عبر 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 للنص الأساسي، Bold للعناوين). يتم توصيل الخطوط المخصصة عبر UIFontMetrics — الطريقة الصحيحة الوحيدة لتكييف خط طرف ثالث مع النوع الديناميكي.
UIFontMetrics هي فئة تم تقديمها في iOS 11 تقوم بتحجيم أي UIFont بشكل متناسب مع نمط النص المحدد. قبل iOS 11، كان المطورون يستخدمون استدعاءً مباشرًا لـ preferredFontForTextStyle، الذي يعيد فقط خط النظام SF Pro. يحل UIFontMetrics هذه المشكلة: فهو يأخذ أي خط ويعيد نسخته المحجمة، محافظًا على الوزن والنسب.
تحسب طريقة scaledFont(for:) عامل تحجيم بناءً على حجم النص الحالي للمستخدم: إذا تم تحديد كبير، يكون العامل 1.0؛ إذا كان كبير جدًا (AX1) — حوالي 1.3؛ للأقصى (AX5) — حتى 1.8. يتم تطبيق العامل على الحجم الأساسي للخط المخصص، وليس على حجم النظام — وهذا يضمن الحفاظ على نية المصمم في جميع الأحجام.
يوصى باستخدام UIFontMetrics لجميع الخطوط المخصصة في التطبيق. في WWDC 2024، عرضت Apple أداة Accessibility Inspector، التي تتحقق من دعم Dynamic Type وتبرز العناصر التي تستخدم حجم خط ثابت بدلاً من UIFontMetrics. في IT Sectr، قمنا بتطبيق UIFontMetrics في جميع المشاريع منذ 2018 — مما قلل أخطاء تداخل النص بنسبة 35%.
أبسط طريقة للحصول على خط ديناميكي لتسمية. يوضح الكود كيفية تعيين 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، وتقوم التسمية بتحديث الخط دون تدخل يدوي.
عند استخدام خط مخصص (مثل 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، استخدمنا هذا النمط في جميع المشاريع ذات الخطوط المخصصة منذ 2018، مما قضى تمامًا على شكاوى النص الصغير من المستخدمين ذوي الإعاقات البصرية.
إذا قمت بتحديث الخط يدويًا (بدون adjustsFontForContentSizeCategory)، اشترك في إشعار UIContentSizeCategory.didChangeNotification. هذا ضروري لعناصر واجهة المستخدم المخصصة التي لا ترث التحديث التلقائي للخط.
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، يصل الإشعار حتى عند تغيير حجم النص عبر مركز التحكم في التطبيقات التي تدعم Live Text Size.
الأسئلة المتكررة
Dynamic Type متاح على iOS 7 وما بعده. ظهر UIFontMetrics في iOS 11 — قبله كان يُستخدم أسلوب preferredFontForTextStyle مباشرة. في iOS 15+، يدعم النوع الديناميكي أحجام إمكانية وصول إضافية (AX1–AX5) للخطوط الكبيرة. التطبيقات التي تدعم iOS 10 وما دونه تستخدم preferredFontForTextStyle بدون UIFontMetrics، مما يحد الدعم فقط لخط النظام SF Pro.
في Xcode 15+، افتح المحاكي واختر الإعدادات → إمكانية الوصول → العرض وحجم النص → نص أكبر. اسحب شريط التمرير لتغيير الحجم. في Xcode نفسه، هناك Debug → Accessibility Inspector، الذي يبرز العناصر ذات الخط الثابت. للأتمتة، استخدم اختبارًا يغير UISlider الإعدادات عبر XCUITest — مما يضمن إعادة بناء جميع الشاشات بشكل صحيح.
نعم، يتطلب Auto Layout مع النوع الديناميكي استخدام intrinsicContentSize في UILabel و UIButton. في أحجام إمكانية الوصول، قد يتجاوز النص حدود superview — أضف UIScrollView أو زِد قيود leading/trailing. استخدم UIFontMetrics.scaledValue للحشو، بحيث يتم أيضًا تحجيم تباعد الأحرف بشكل متناسب مع الخط.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.