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, која омогућава тексту у апликацији да се аутоматски прилагоқава системским подешавањима величине фонта. Корисник може да повећigа или смањи фонт у свим апликацијама одједном — без потребе да мења подешавања у свакој апликацији појединачно.

Према Apple WWDC 2023, „Make Your App Visually Accessible“, више од 40% корисника iOS-а мења величину фонта у односу на стандардну. За старосну групу 65+ овај показатељ достиже 70%. Dynamic Type је обавезан за сертификацију приступачности App Store-а. Недостатак подршке је разлог за одбијање апликације на прегледу.

Принцип рада: апликација користи UIFont.preferredFont(forTextStyle:) уместо UIFont(name:size:). 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 позива traitCollectionDidChange на свим UIView-овима. У овој методи потребно је ажурирати фонтове и прерачунати изглед. 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-а. Фиксне ширине и висине (>=, <=) се ломе на величинама приступачности. Користите intrinsicContentSize за UILabel — он аутоматски израчунава висину према тренутној величини фонта.

Правила прилагодљивог изгледа:

  • UIStackView са distribution = fill и spacing = >= 8 — елементи ће бити премештени у следећи ред
  • UITableViewCell са automaticDimension — висина ћелије се прилагоћава садржају
  • numberOfLines = 0 на UILabel-у — текст се не скраћује, већ прелама
  • Дугмићи са edgeInsets — додајте размаке на нивоима приступачности путем traitCollection.preferredContentSizeCategory

За дугачке текстове (нпр. чланци, услови коришћења) поставите minimumScaleFactor на UILabel-у — ово смањује текст као посљедње средство када 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 креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође