Dynamic Type — уграђена iOS функција која аутоматски мења величину фонта у апликацији у складу са системским подешавањима корисника. Корисник подешава преферирану величину текста у Подешавања → Екран и сјај → Величина текста, и све апликације које подржавају Dynamic Type прилагоқавају се без додатних радњи. Према Apple Human Interface Guidelines, 2024, подршка Dynamic Type је обавезни услов за објављивање у App Store-у, јер је то основни елеменат приступачности на 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 се појавио у iOS 7 заједно са „платним“ дизајном. У iOS 10 додата је подршка за прилагођене фонтове путем UIFontMetrics. iOS 11 је увео нивое приступачности (до AccessibilityXXXL). iOS 15 је додао Dynamic Type у SwiftUI са аутоматском подршком. Сваким издањем Apple пооштрава захтеве: од iOS 17, апликације без подршке Dynamic Type-а добијају упозорење при учитавању у App Store Connect.
iOS пружа 8 стилова текста, сваки са унапред дефинисаном величином и изгледом за стандардну поставку:
| Стил | Константа | Величина (L) | Намена |
|---|---|---|---|
| Large Title | .largeTitle | 34px | Главни наслов екрана |
| Title 1 | .title1 | 28px | Наслов секције |
| Title 2 | .title2 | 22px | Поднаслов |
| Title 3 | .title3 | 20px | Наслов картице |
| Headline | .headline | 17px (bold) | Подебљано за акцент |
| Body | .body | 17px | Основни текст |
| Callout | .callout | 16px | Помоћни текст |
| Caption 1 | .caption1 | 12px | Натпис испод слике |
| Caption 2 | .caption2 | 11px | Ситан натпис |
| Footnote | .footnote | 13px | Фуснота, напомена |
Коришћење правог стила није само „изглед“. UIFont.TextStyle.body у AccessibilityXXXL моду може да достигне 53px. Ако апликација користи фиксни фонт 17px за body, текст ће постати нечитклјив за кориснике који су повећали фонт.
Dynamic Type не само скалира — чува визуелну хијерархију. Large Title је увек већи од Title 1, који је већи од Body-а, без обзира на ниво скалирања. Коефицијенти скалирања се разликују: наслови се скалирају активније од основног текста да би хијерархија била очувана чак и на нивоима приступачности.
iOS подржава 11 нивоа скалирања текста, подељених у двије категорије:
Разлика између XS и AccessibilityXXXL за стил body је од 14px до 53px — скоро 4×. Изглед дизајниран за 17px се потпуно ломи на 53px: текст излази из граница, дугмићи се преклапају, ћелије налазе једна на другу.
Проверите тренутну категорију у коду:
let category = UIApplication.shared.preferredContentSizeCategory
// .extraSmall, .small, .medium, .large, .extraLarge ...
if category.isAccessibilityCategory {
// Укључи алтернативни изглед
}
Категорија величине текста је доступна кроз traitCollection.uiContentSizeCategory. При промени системске поставке, iOS позива traitCollectionDidChange на свим UIView-овима. У овој методи потребно је ажурирати фонтове и прерачунати изглед. SwiftUI то ради аутоматски — UIKit захтева ручно претплаћивање.
За UICollectionView користите UICollectionViewCompositionalLayout — он аутоматски прилагоқава број колона према ширини екрана и величини текста. На нивоима приступачности пређите са двоколонског на једноколонски распоред да текст не буде одсецен и елементи се не преклапају. Користите условни распоред: за regular width — двије колоне, за compact или accessibility — једна колона.
Основна имплементација у UIKit-у — UIFont.preferredFont(forTextStyle:). Ова метода враћа фонт скалиран према тренутној системској поставци:
titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
bodyLabel.font = UIFont.preferredFont(forTextStyle: .body)
За прилагођене фонтове користите UIFontMetrics:
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 користи исту криву скалирања као и preferredFont. Можете поставити fromTextStyle: .body, .headline итд. Сваки стил има сопствени коефицијент скалирања. Body скалира се умерено, Large Title — агресивно. Ако се ваш прилагођени фонт користи за основни текст, користите .body.
У SwiftUI-ју, подршка за Dynamic Type је уграђена подразумевано. Сви системски модификатори (.font(.body), .font(.title)) се аутоматски скалирају. Програмер не мора да позива UIFont.preferredFont.
Примјер:
Text("Основни текст")
.font(.body)
.lineLimit(nil)
.minimumScaleFactor(0.5)
За прилагођене скале користите DynamicTypeSize:
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var body: some View {
Text("Прилагодљиви текст")
.font(.body)
.padding(dynamicTypeSize <= .large ? 8 : 16)
}
SwiftUI аутоматски ажурира приказ при промени системске величине текста — без икаквих додатних претплата на обавештења.
Модификатор .font(.body) ради само за системски фонт. За прилагођене фонтове у SwiftUI-ју користите Font.custom са UIFontMetrics испод хаубе. Од iOS 16, SwiftUI подржава DynamicTypeSize у @Environment-у, што омогућава прилагођавање размака и компоновање.
Auto Layout — обавезан услов за подршку Dynamic Type-а. Фиксне ширине и висине (>=, <=) се ломе на величинама приступачности. Користите intrinsicContentSize за UILabel — он аутоматски израчунава висину према тренутној величини фонта.
Правила прилагодљивог изгледа:
За дугачке текстове (нпр. чланци, услови коришћења) поставите minimumScaleFactor на UILabel-у — ово смањује текст као посљедње средство када Auto Layout не може да смјести садржај. Вриједност 0.5 значи да се фонт може смањити на 50% препоручене величине.
Примјер прилагођавања размака према категорији величине:
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 је обавезан на нивоима приступачности.
Xcode симулатор омогућава промену величине текста: у менију симулатора Settings → Accessibility → Display & Text Size → Larger Text. Пребацујте се између свих 11 нивоа и проверите да текст није одсечен, дугмићи су доступни и изглед није покварен.
За аутоматизовано тестирање користите поставку contentSizeCategory у XCUIApplication:
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-а се открива управо на нивоима приступачности, јер програмери тестирају само стандардне величине.
Xcode Accessibility Inspector показује које фонтове користи изабрани елеменат — фиксне или скалирајуће. Ако елеменат не реагује на промену величине текста у симулатору, то значи да се користи фиксни фонт. Замењите га са UIFont.preferredFont или UIFontMetrics.
Често постављана питања
То је аутоматско скалирање текста у апликацији према системским подешавањима величине. Корисник мења величину у Подешавањима — све апликације које подржавају ову функцију се прилагођавају без учешћа програмера.
Не. За прилагођене фонтове користите UIFontMetrics(scaledFont:). Метода скалира било који фонт у односу на наведени стил текста, чувајући пропорције.
11 нивоа: 5 стандардних (XS, S, M, L, XL) и 6 нивоа приступачности (од AccessibilityXL до AccessibilityXXXXXL). Величина фонта body може да варира од 14px до 53px.
У UIKit-у путем UIContentSizeCategory.didChangeNotification. У SwiftUI-ју користите @Environment(\.dynamicTypeSize) — приказ ће се ажурирати аутоматски при промени системске поставке.
Корисници са повећаним фонтом видеће одсечен текст, елементе који се преклапају и нефункционалне дугмиће. Апликација може бити одбијена на App Store прегледу због кршења захтева приступачности.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође