Dynamic Type: مفاهیم کلیدی، سبک‌های متنی و عملکرد در iOS

نویسنده: IT Sectr منتشر شده: 2026-05-16 زمان مطالعه: 9 دقیقه

Dynamic Type — یک قابلیت داخلی iOS است که به‌طور خودکار اندازه فونت را در برنامه مطابق تنظیمات سیستم کاربر تغییر می‌دهد. کاربر اندازه متن مورد نظر خود را در تنظیمات → صفحه و روشنایی → اندازه متن تعیین می‌کند، و همه برنامه‌هایی که Dynamic Type را پشتیبانی می‌کنند بدون اقدام اضافی سازگار می‌شوند. به استناد Apple Human Interface Guidelines, 2024، پشتیبانی از Dynamic Type یک الزام انتشار در App Store است، زیرا این یک عنصر اساسی دسترس‌پذیری در پلتفرم iOS است.

نکات کلیدی

  • Dynamic Type — مکانیسم iOS برای مقیاس‌پذیری خودکار متن بر اساس تنظیمات سیستم اندازه فونت
  • پشتیبانی از طریق سبک‌های متنی (UIFont.TextStyle) ارائه می‌شود — body، headline، caption، title و سایر
  • سیستم 11 سطح مقیاس‌پذیری از XSmall تا AccessibilityXXXL را پشتیبانی می‌کند
  • برای فونت‌های سفارشی از روش UIFontMetrics استفاده می‌شود که هر فونتی را نسبت به سبک body مقیاس می‌کند
  • چیدمان باید سازگارشو باشد — UIStackView، Auto Layout و ارتفاع دینامیک سلول‌ها الزامی هستند

Dynamic Type در iOS چیست

Dynamic Type — فناوری iOS است که در iOS 7 ظاهر شد و به متن در برنامه اجازه می‌دهد تا به‌طور خودکار با تنظیمات سیستم اندازه فونت سازگار شود. کاربر می‌تواند فونت را در همه برنامه‌ها به‌طور همزمان بزرگ‌تر یا کوچک‌تر کند — بدون نیاز به تغییر تنظیمات در هر برنامه به‌صورت جداگانه.

به استناد Apple WWDC 2023، «Make Your App Visually Accessible»، بیش از 40% از کاربران iOS اندازه فونت را از حالت پیش‌فرض تغییر می‌دهند. برای گروه سنی 65+، این شاخص به 70% می‌رسد. Dynamic Type یک الزام گواهی دسترس‌پذیری App Store است. نبود پشتیبانی دلیل رد برنامه در بررسی است.

اصل کار: برنامه به جای UIFont(name:size:) از UIFont.preferredFont(forTextStyle:) استفاده می‌کند. iOS به‌طور خودکار فونتی را مقیاس‌شده بر اساس تنظیم جاری سیستم برمی‌گرداند. هنگام تغییر اندازه در تنظیمات، iOS اطلاع‌رسانی UIContentSizeCategory.didChangeNotification را تولید می‌کند — برنامه باید چیدمان را مجدداً محاسبه کند.

تاریخچه توسعه Dynamic Type

Dynamic Type در iOS 7 همراه با طراحی «تخت» ظاهر شد. در iOS 10 پشتیبانی از فونت‌های سفارشی از طریق UIFontMetrics اضافه شد. iOS 11 سطوح دسترس‌پذیری (تا AccessibilityXXXL) را معرفی کرد. iOS 15 Dynamic Type را با پشتیبانی خودکار در SwiftUI اضافه کرد. با هر نسخه، Apple مطالبات را سفت‌تر می‌کند: از iOS 17، برنامه‌هایی که از Dynamic Type پشتیبانی نمی‌کنند هنگام بارگذاری در App Store Connect هشدار دریافت می‌کنند.

سبک‌های متنی UIFont.TextStyle

iOS 8 سبک متنی را ارائه می‌دهد، هر کدام با اندازه و قلم از پیش تعیین‌شده برای تنظیم پیش‌فرض:

سبکثابتاندازه (L)کاربرد
Large Title.largeTitle34pxعنوان اصلی صفحه
Title 1.title128pxعنوان بخش
Title 2.title222pxزیرعنوان
Title 3.title320pxعنوان کارت
Headline.headline17px (bold)ضخیم برای تاکید
Body.body17pxمتن اصلی
Callout.callout16pxمتن کمکی
Caption 1.caption112pxشرح زیر تصویر
Caption 2.caption211pxشرح کوچک
Footnote.footnote13pxپانویس، یادداشت

استفاده از سبک مناسب فقط «ظاهر» نیست. UIFont.TextStyle.body در حالت AccessibilityXXXL می‌تواند به 53px برسد. اگر برنامه از فونت ثابت 17px برای body استفاده کند، متن برای کاربرانی که فونت را بزرگ کرده‌اند غیرقابل خوانش می‌شود.

سلسله‌مراتب دیداری از طریق سبک‌ها

Dynamic Type فقط مقیاس نمی‌کند — آن سلسله‌مراتب دیداری را حفظ می‌کند. Large Title همیشه از Title 1 بزرگ‌تر است، که آن هم از Body بزرگ‌تر است، صنظر از سطح مقیاس. ضرایب مقیاس متفاوتند: عناوین فعال‌تر از متن اصلی مقیاس می‌شوند تا سلسله‌مراتب حتی در سطوح دسترس‌پذیری حفظ شود.

سطوح مقیاس‌پذیری

iOS 11 سطح مقیاس‌پذیری متن را در دو دسته پشتیبانی می‌کند:

  • اندازه‌های ستاندارد (5 سطح): XS، S، M، L (پیش‌فرض)، XL
  • اندازه‌های دسترس‌پذیری (6 سطح): accessibilityXL، accessibilityXXL، accessibilityXXXL، accessibilityXXXXL، accessibilityXXXXXL، accessibilityXXXXXXL

تفاوت بین XS و AccessibilityXXXL برای سبک body از 14px تا 53px است — تقریباً 4×. چیدمانی که برای 17px طراحی شده در 53px کاملاً مخروب می‌شود: متن از حدود خارج می‌شود، دکمه‌ها بر یکدیگر می‌افتند، سلول‌ها روی هم می‌افتند.

دسته جاری را در کد بررسی کنید:

swift
let category = UIApplication.shared.preferredContentSizeCategory
// .extraSmall, .small, .medium, .large, .extraLarge ...
if category.isAccessibilityCategory {
    // فعال‌سازی چیدمان جایگزین
}

traitCollection و اندازه متن

دسته اندازه متن از طریق traitCollection.uiContentSizeCategory قابل دسترس است. هنگام تغییر تنظیم سیستم، iOS روی همه UIViewها traitCollectionDidChange را فراخوان می‌کند. در این روش باید فونت‌ها را به‌روز کرده و چیدمان را مجدداً محاسبه کرد. SwiftUI این کار را به‌طور خودکار انجام می‌دهد — UIKit نیاز به اشتراک دستی دارد.

برای UICollectionView از UICollectionViewCompositionalLayout استفاده کنید — آن تعداد ستون‌ها را به‌طور خودکار با عرض صفحه و اندازه متن سازگار می‌کند. در سطوح دسترس‌پذیری از چیدمان دو ستونی به یک ستونی تغییر کنید تا متن بوریده نشود و عناصر بر یکدیگر نفتند. از چیدمان شرطی استفاده کنید: برای regular width — دو ستون، برای compact یا accessibility — یک ستون.

پیاده‌سازی در UIKit

پیاده‌سازی پایه در UIKit — UIFont.preferredFont(forTextStyle:). این روش فونتی را مقیاس‌شده بر اساس تنظیم جاری سیستم برمی‌گرداند:

swift
titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
bodyLabel.font = UIFont.preferredFont(forTextStyle: .body)

برای فونت‌های سفارشی از UIFontMetrics استفاده کنید:

swift
let customFont = UIFont(name: "Montserrat-Regular", size: 16)!
titleLabel.font = UIFontMetrics(forTextStyle: .body)
    .scaledFont(for: customFont)

// پیگیری تغییرات اندازه
NotificationCenter.default.addObserver(
    self,
    selector: #selector(preferredContentSizeChanged),
    name: UIContentSizeCategory.didChangeNotification,
    object: nil
)

برای UILabel در Interface Builder کافی است فونت را به عنوان سبک متنی (Text Style) تنظیم کرده و «Automatically Adjusts Font» را فعال کنید. برای فونت‌های سفارشی، IB از UIFontMetrics پشتیبانی نمی‌کند — فقط از طریق کد.

UIFontMetrics و منحنی مقیاس

UIFontMetrics از همان منحنی مقیاسی استفاده می‌کند که preferredFont. می‌توانید fromTextStyle: .body، .headline و غیره را تنظیم کنید. هر سبک ضریب مقیاس خود را دارد. Body متعادل مقیاس می‌شود، Large Title به‌طور فراوان. اگر فونت سفارشی شما برای متن اصلی استفاده می‌شود، از .body استفاده کنید.

Dynamic Type در SwiftUI

در SwiftUI، پشتیبانی از Dynamic Type به‌طور پیش‌فرض داخلی است. همه تغییردهنده‌های سیستمی (.font(.body)، .font(.title)) به‌طور خودکار مقیاس می‌شوند. توسعه‌دهنده نیازی به فراخوان UIFont.preferredFont ندارد.

مثال:

swift
Text("متن اصلی")
    .font(.body)
    .lineLimit(nil)
    .minimumScaleFactor(0.5)

برای مقیاس‌های سفارشی از DynamicTypeSize استفاده کنید:

swift
@Environment(\.dynamicTypeSize) var dynamicTypeSize

var body: some View {
    Text("متن سازگارشو")
        .font(.body)
        .padding(dynamicTypeSize <= .large ? 8 : 16)
}

SwiftUI به‌طور خودکار نمایش را هنگام تغییر اندازه متن سیستم به‌روز می‌کند — بدون هیچ اشتراک اطلاع‌رسانی اضافه.

محدودیت Dynamic Type در SwiftUI

تغییردهنده .font(.body) فقط برای فونت سیستم کار می‌کند. برای فونت‌های سفارشی در SwiftUI از Font.custom با UIFontMetrics در زیرساخت استفاده کنید. از iOS 16، SwiftUI از DynamicTypeSize در @Environment پشتیبانی می‌کند که امکان سازگاری فاصله‌ها و چیدمان را فراهم می‌کند.

سازگاری چیدمان برای فونت‌های بزرگ

Auto Layout — شرط الزامی پشتیبانی از Dynamic Type است. عرض‌ها و ارتفاع‌های ثابت (>=, <=) در اندازه‌های دسترس‌پذیری مخروب می‌شوند. برای UILabel از intrinsicContentSize استفاده کنید — آن ارتفاع را بر اساس اندازه فونت جاری به‌طور خودکار محاسبه می‌کند.

قوانین چیدمان سازگارشو:

  • UIStackView با distribution = fill و spacing = >= 8 — عناصر به ردیف بعدی منتقل می‌شوند
  • UITableViewCell با automaticDimension — ارتفاع سلول با محتوا سازگار می‌شود
  • numberOfLines = 0 در UILabel — متن بوریده نمی‌شود، بلکه جابجا می‌شود
  • دکمه‌ها با edgeInsets — در سطوح دسترس‌پذیری از طریق traitCollection.preferredContentSizeCategory فاصله اضافه کنید

برای متون طولانی (مانند مقالات، شرایط استفاده) روی UILabel minimumScaleFactor را تنظیم کنید — این متن را به عنوان آخرین چاره کوچک می‌کند زمانی که Auto Layout نتواند محتوا را جای دهد. مقدار 0.5 به معنای این است که فونت می‌تواند تا 50% اندازه ترجیحی کوچک شود.

مثال سازگاری فاصله‌ها با دسته اندازه:

swift
let isAccessibility = traitCollection
    .preferredContentSizeCategory.isAccessibilityCategory
stackView.spacing = isAccessibility ? 16 : 8
button.contentEdgeInsets = isAccessibility
    ? UIEdgeInsets(top: 16, left: 24, bottom: 16, right: 24)
    : UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)

مشکلات رایج چیدمان در سطوح دسترس‌پذیری

بوریدگی متن — UILabel با numberOfLines = 1 و عرض ثابت متن را در AccessibilityXL بهار می‌کند. راه‌حل: numberOfLines = 0 و trailing constraint. تداخل عناصر — دکمه‌هایی با ارتفاع ثابت بر یکدیگر می‌افتند. راه‌حل: UIStackView با automatic spacing. خروج از حدود صفحه — ScrollView در سطوح دسترس‌پذیری الزامی است.

آزمایش Dynamic Type

شبیه‌ساز Xcode امکان تغییر اندازه متن را فراهم می‌کند: در منوی شبیه‌ساز Settings → Accessibility → Display & Text Size → Larger Text. بین هر 11 سطح تغییر کنید و بررسی کنید که متن بوریده نمی‌شود، دکمه‌ها در دسترس هستند و چیدمان مخروب نیست.

برای آزمایش خودکار از تنظیم contentSizeCategory در XCUIApplication استفاده کنید:

swift
func testAccessibilitySizes() {
    let app = XCUIApplication()
    app.launchArguments += [
        "-UIPreferredContentSizeCategoryName",
        "UICTContentSizeCategoryAccessibilityXXXL"
    ]
    app.launch()
    app.scrollViews.buttons["ارسال"].tap()
    XCTAssertTrue(app.staticTexts["فرم ارسال شد"]
        .waitForExistence(timeout: 5))
}

XCUITest با launchArguments مختلف امکان بررسی تمام سطوح مقیاس را در CI فراهم می‌کند. فراموش نکنید دسته‌های دسترس‌پذیری را جداگانه بررسی کنید — آنها بیشتر از هر چیز چیدمان را مخروب می‌کنند. به استناد Apple، 70% از باگ‌های Dynamic Type در همین سطوح دسترس‌پذیری شناسایی می‌شوند، زیرا توسعه‌دهندگان فقط اندازه‌های ستاندارد را آزمایش می‌کنند.

Accessibility Inspector: بررسی Dynamic Type

Xcode Accessibility Inspector نشان می‌دهد که عنصر انتخابی از چه فونت‌هایی استفاده می‌کند — ثابت یا مقیاس‌پذیر. اگر عنصر به تغییر اندازه متن در شبیه‌ساز پاسخ نمی‌دهد، به معنای استفاده از فونت ثابت است. آن را با UIFont.preferredFont یا UIFontMetrics جایگزین کنید.

سوالات متداول

Dynamic Type در iOS به زبان ساده چیست؟

این یک مقیاس‌پذیری خودکار متن در برنامه مطابق تنظیمات سیستم اندازه است. کاربر اندازه را در تنظیمات تغییر می‌دهد — همه برنامه‌های پشتیبانی‌کننده بدون نیاز به توسعه‌دهنده سازگار می‌شوند.

آیا Dynamic Type فقط با فونت‌های سیستم کار می‌کند؟

خیر. برای فونت‌های سفارشی از UIFontMetrics(scaledFont:) استفاده کنید. این روش هر فونتی را نسبت به سبک متنی مشخص‌شده مقیاس می‌کند، تناسب را حفظ می‌کند.

iOS چند سطح مقیاس‌پذیری را پشتیبانی می‌کند؟

11 سطح: 5 ستاندارد (XS، S، M، L، XL) و 6 سطح دسترس‌پذیری (از AccessibilityXL تا AccessibilityXXXXXL). اندازه فونت body می‌تواند از 14px تا 53px متغیر باشد.

چگونه در تغییرات اندازه متن مشترک شوم؟

در UIKit از طریق UIContentSizeCategory.didChangeNotification. در SwiftUI از @Environment(\.dynamicTypeSize) استفاده کنید — نمایش به‌طور خودکار هنگام تغییر تنظیم سیستم به‌روز می‌شود.

اگر Dynamic Type را پشتیبانی نکنم چه می‌شود؟

کاربران با فونت بزرگ‌شده متن بوریده، عناصر متداخل و دکمه‌های غیرقابل استفاده خواهند دید. برنامه می‌تواند در بررسی App Store به دلیل نقض مطالبات دسترس‌پذیری رد شود.

خلاصه

  • Dynamic Type — مکانیسم داخلی iOS برای مقیاس‌پذیری متن مطابق تنظیمات سیستم; برای App Store الزامی است
  • برای فونت‌های سیستم از UIFont.preferredFont(forTextStyle:) و برای فونت‌های سفارشی از UIFontMetrics استفاده کنید
  • iOS 11 سطح مقیاس‌پذیری را پشتیبانی می‌کند — از XS تا AccessibilityXXXXXL (14–53px برای body)
  • در SwiftUI، Dynamic Type از طریق .font(.body) و @Environment(\.dynamicTypeSize) خودکار کار می‌کند
  • چیدمان باید سازگارشو باشد: UIStackView، automaticDimension در جداول، numberOfLines = 0
  • هر 11 سطح، به‌ویژه دسته‌های دسترس‌پذیری را آزمایش کنید — 70% چیدمان‌ها در آنها مخروب می‌شوند
  • اشتراک در UIContentSizeCategory.didChangeNotification برای برنامه‌های UIKit الزامی است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید