@ScaledMetric — SwiftUI property wrapper, amely automatikusan skálázza a numerikus értéket a felhasználó Dynamic Type beállításainak megfelelően. Az érték @ScaledMetric-be van csomagolva és újraszámolásra kerül a rendszer betűméretének változásakor, garantálva a felület hozzáférhetőségét látássérült emberek számára. Az Apple Developer Documentation (2026) szerint az @ScaledMetric az UIFontMetrics skálát használja a relatív skála kiszámításához a preferred content size category alapján. További információ az akadálymentesítésről: anyag a SwiftUI akadálymentesítésről.
Főbb pontok
@ScaledMetric — iOS 14-ben hozzáadott SwiftUI property wrapper, amely automatikusan skálázza a numerikus értéket (CGFloat, Int, Double) az aktuális Dynamic Type betűméretre. Ellentétben a .font(.body) betűtípusokhoz való használatával, az @ScaledMetric bármilyen numerikus paramétert skáláz: padding, spacing, cornerRadius, iconSize — mindent, aminek arányosan kell nőnie nagy szövegnél.
Az @ScaledMetric fő feladata a nem szöveges felületelemek akadálymentesítési skálázásának biztosítása. Amikor a felhasználó megnöveli a betűméretet az iOS beállításaiban, a gomboknak, ikonoknak és távolságoknak arányosan kell nőniük, hogy a felület egyensúlyban maradjon. Az @ScaledMetric automatikusan oldja meg ezt a feladatot, a szorzók kézi kiszámítása nélkül.
Alap szintaxis Az @ScaledMetric alapértelmezett értéket és opcionális relativeTo paramétert használ. Ha a relativeTo meg van adva, a skálázás egy adott szövegstílushoz (UIFontTextStyle) van kötve. Ha nincs — a .body skála használatos.
struct AccessibleButton: View {
@ScaledMetric private var padding: CGFloat = 12
@ScaledMetric(relativeTo: .title) private var iconSize: CGFloat = 24
var body: some View {
Label("Küldés", systemImage: "checkmark.circle.fill")
.font(.body)
.padding(padding)
.imageScale(.init(rawValue: iconSize / 24) ?? .medium)
}
}
padding a .body-hoz (alapértelmezett), iconSize a .title-hez képest skálázódik. Nagy szövegnél a távolságok és az ikon arányosan nőnek. @ScaledMetric nélkül a távolságok 12 pt maradnának bármilyen betűméretnél, ami vizuális egyensúlyhiányhoz vezetne.
Az @ScaledMetric mechanizmusa a UIKit-ből származó UIFontMetrics-en alapul. Amikor a SwiftUI létrehoz egy @ScaledMetric példányt, kiszámít egy szorzót az aktuális preferred content size category (UIContentSizeCategory) alapján. Az alapérték megszorzásra kerül a UIFontMetrics scaledValue-jával a megadott szövegstílushoz.
Matematikailag: ScaledMetricValue = baseValue × UIFontMetrics.scaledValue(for: relativeTo). Ha a relativeTo nincs megadva, a .body-hoz kötött UIFontMetrics.default használatos. Dynamic Type változásakor a SwiftUI újra létrehozza a View törzsét, az @ScaledMetric kiszámítja az új scaledValue-ot, és a UI automatikusan frissül a @State-szerű PropertyWrappers mechanizmusán keresztül.
Az iOS skála 11 méretet tartalmaz: .extraSmall (5 pt) és .accessibilityExtraExtraExtraLarge (77 pt .body esetén) között. A .body skálázási együtthatója 0.85 (XS) és 1.71 (XXXL) között változik az alapértékhez képest. Az @ScaledMetric pontosan ezt a skálát használja, így a 12 pt padding érték ~20 pt lehet a maximális akadálymentesítési méretnél.
| Content Size Category | Együttható (body) | Példa @ScaledMetric(12) |
|---|---|---|
| extraSmall | 0.85 | ~10 pt |
| small | 0.93 | ~11 pt |
| medium (default) | 1.00 | 12 pt |
| large | 1.07 | ~13 pt |
| extraLarge | 1.15 | ~14 pt |
| extraExtraLarge | 1.28 | ~15 pt |
| accessibilityExtraLarge | 1.47 | ~18 pt |
| accessibilityXXXL | 1.71 | ~20 pt |
relativeTo kiválasztása: használja a .body-t a fő szöveghez kapcsolódó értékekhez (padding, spacing listákban), .title-t nagy elemekhez (iconSize, imageSize), .caption-t kis elemekhez (badge méret). Ez biztosítja, hogy az elemek a környező szöveggel összhangban skálázódjanak.
Dynamic Type — iOS funkció, amely lehetővé teszi a felhasználónak a rendszer betűméretének beállítását a Settings → Display & Brightness → Text Size menüpontban. A változás globálisan érvényesül az összes alkalmazásra. Az @ScaledMetric automatikusan reagál erre a változásra: a SwiftUI frissíti az összes @ScaledMetric változót a UIContentSizeCategory változásakor.
Fontos: Az @ScaledMetric csak numerikus értékeket skáláz, de nem kezeli közvetlenül a betűtípusokat. Betűtípusokhoz használja a .font()-ot szövegstílussal (.body, .title, .headline) — a SwiftUI automatikusan skálázza a betűtípust. Az @ScaledMetric kiegészíti a betűtípus skálázást padding, spacing és elem méretek esetében.
Canvas Preview támogatja a Dynamic Type-ot: a Canvas eszköztárán van egy Text Size (A–A) csúszka a UI ellenőrzéséhez különböző betűméreteknél. Használja az @ScaledMetric-kel, hogy megbizonyosodjon a távolságok és méretek helyes skálázódásáról.
struct CardView: View {
@ScaledMetric private var cornerRadius: CGFloat = 16
@ScaledMetric private var spacing: CGFloat = 8
var body: some View {
VStack(spacing: spacing) {
Text("Kártya címe")
.font(.headline)
Text("Leírás dynamic type támogatással")
.font(.body)
}
.padding(spacing * 2)
.background(.regularMaterial)
.cornerRadius(cornerRadius)
}
}
struct CardView_Previews: PreviewProvider {
static var previews: some View {
CardView()
.dynamicTypeSize(.large)
.previewDisplayName("Large")
CardView()
.dynamicTypeSize(.accessibility5)
.previewDisplayName("Accessibility 5")
}
}
cornerRadius 16 pt-ról ~27 pt-ra skálázódik maximális akadálymentesítési méretnél. spacing — 8-ról ~14 pt-ra. Ez biztosítja, hogy a kártya vizuálisan egyensúlyban maradjon bármilyen betűméretnél.
Példa: ikon Dynamic Type támogatással. Az Image(systemName:) ikonok mérete alapértelmezés szerint nem skálázódik Dynamic Type alatt. Az @ScaledMetric megoldja ezt a problémát: az imageScale vagy a frame méret módosításával az aktuális skálázási tényező alapján.
struct IconLabel: View {
let title: String
let icon: String
@ScaledMetric private var iconDimension: CGFloat = 28
@ScaledMetric(relativeTo: .body) private var spacing: CGFloat = 6
var body: some View {
HStack(spacing: spacing) {
Image(systemName: icon)
.resizable()
.frame(width: iconDimension, height: iconDimension)
Text(title)
.font(.body)
}
}
}
Példa: akadálymentes badge-komponens. A számmal ellátott badge-nek arányosan kell skálázódnia a szöveggel. Az @ScaledMetric a badge minimális méretéhez biztosítja, hogy a kerek badge látható maradjon nagy betűméretnél.
struct BadgeView: View {
let count: Int
@ScaledMetric(relativeTo: .caption) private var badgeSize: CGFloat = 20
@ScaledMetric(relativeTo: .caption) private var fontScale: CGFloat = 1
var body: some View {
ZStack {
Circle()
.fill(.red)
.frame(width: badgeSize, height: badgeSize)
Text("\(count)")
.font(.caption)
.foregroundColor(.white)
.scaleEffect(fontScale)
}
.fixedSize()
}
}
fontScale emellett skálázza a Circle tartalmát a megnövelt badgeSize-hoz igazodva. fontScale nélkül a badge-en belüli szöveg nem férne el nagy betűméretnél.
@ScaledMetric és @State — mindkettő property wrapper, amelyek változásokat követnek, de eltérő frissítési forrásokkal. A @State programozott változásnál frissíti az értéket ($stateBinding-en keresztül). Az @ScaledMetric automatikusan frissíti az értéket a rendszer Dynamic Type változásakor, de nem engedi az érték közvetlen módosítását kódból.
A kulcsfontosságú különbség: @ScaledMetric — read-only a fejlesztő számára és write-only a rendszer számára. Nem módosíthatja a scaledValue-t setteren keresztül — a SwiftUI számítja ki az alapérték és az aktuális Dynamic Type alapján. A @State ezzel szemben teljesen a fejlesztő által kezelt. Ha olyan értékre van szüksége, amely egyszerre skálázódik Dynamic Type alatt és programozottan is változtatható — kombinálja az @ScaledMetric-et a @State-tel, vagy használjon számított tulajdonságot.
| Jellemző | @ScaledMetric | @State |
|---|---|---|
| Frissítés forrása | Dynamic Type (rendszer) | Programozott (fejlesztő) |
| Érték típusa | CGFloat, Int, Double | Bármilyen |
| Módosítás kódból | Nem lehet | Binding-en keresztül lehet |
| View újrarajzolása | Dynamic Type változásakor | Érték változásakor |
| iOS verzió | iOS 14+ | iOS 13+ |
Kombinált minta: ha programozottan kell módosítania a padding-et (pl. kattintás animáció) és egyidejűleg skáláznia Dynamic Type alatt, hozzon létre egy @ScaledMetric-et az alap skálázott értékhez és egy @State-t az animációs szorzóhoz. A végső érték = scaledValue × animationMultiplier.
Hiba 1: @ScaledMetric használata betűtípusokhoz. Az @ScaledMetric számokat skáláz, nem betűtípusokat. Betűtípusokhoz használja a .font(.body)-t — a SwiftUI automatikusan alkalmazza a Dynamic Type-ot. Soha ne használja az @ScaledMetric-et font(.system(size: scaledSize))-val — ez tönkreteszi a rendszer akadálymentesítését.
Hiba 2: relativeTo hiánya heterogén elemeknél. Ha padding (.body-hoz kapcsolódó) és iconSize (.title-hez kapcsolódó) is van, adja meg a helyes relativeTo-t mindegyikhez. relativeTo nélkül mindkettő .body szerint skálázódik, ami az ikon aránytalan növekedéséhez vezet a szöveges kontextusához képest.
Hiba 3: @ScaledMetric ViewModel/@ObservableObject osztályban. Az @ScaledMetric egy SwiftUI property wrapper, amely csak View-n belül működik. Nem használható ViewModel-ben vagy szolgáltatásokban. A ViewModel-ben történő skálázáshoz adja át a skálázott értéket a View-ból paraméterként, vagy használja az @Environment(\.sizeCategory)-t a View-ban.
@Environment(\.sizeCategory) — alternatív módszer az aktuális Dynamic Type lekérésére a View-ban. Használja, amikor több vezérlésre van szüksége: egyéni szorzó kiszámítása, sizeCategory átadása ViewModel-nek vagy kombinálás @ScaledMetric-kel a rugalmas skálázáshoz.
struct CustomScaledView: View {
@Environment(\.sizeCategory) private var sizeCategory
@ScaledMetric private var basePadding: CGFloat = 12
private var extraPadding: CGFloat {
if sizeCategory >= .accessibilityLarge {
return basePadding * 0.5
}
return 0
}
var body: some View {
Text("Egyéni skálázott tartalom")
.font(.body)
.padding(basePadding + extraPadding)
}
}
Extra távolság Az extraPadding csak akadálymentesítési méreteknél adódik hozzá, több helyet biztosítva a nagy szöveg számára az alap @ScaledMetric logika megváltoztatása nélkül.
Gyakran ismételt kérdések
@ScaledMetric — hivatalos SwiftUI property wrapper számok skálázásához. @ScaledFont nem létezik szabványos API-ként — ez egy közösség által megvalósított egyéni wrapper. Betűtípusokhoz mindig a beépített .font()-ot használja szövegstílusokkal (.body, .title), az @ScaledMetric-et pedig padding, spacing és méretek esetén.
@ScaledMetric iOS 14+, watchOS 7+, tvOS 14+ és macOS 11+ rendszeren érhető el. watchOS-en a Dynamic Type kisebb tartományra korlátozott — .extraSmall és .extraLarge közötti méretek akadálymentesítési méretek nélkül. tvOS-en a Dynamic Type hiányzik — az @ScaledMetric mindig az alapértéket adja vissza.
Igen, az @ScaledMetric teszteléséhez hozzon létre egy View-t @ScaledMetric-kel, és adja át a .sizeCategory environment értéket .environment(\.sizeCategory, .extraExtraLarge) segítségével. Ezután szerezze be az elem méretét GeometryReader vagy SwiftUI Inspector segítségével. Alternatívaként ellenőrizze a skálázási logikát UIFontMetrics segítségével egy külön modulban.
.dynamicTypeSize — View módosító, amely korlátozza a maximális Dynamic Type-ot egy hierarchiában (pl. .dynamicTypeSize(...large)). Az @ScaledMetric figyelembe veszi ezt a korlátozást: ha a .dynamicTypeSize be van állítva, a skálázott érték nem haladja meg a megfelelő méretet. Kombinálja mindkét API-t a pontos vezérléshez.
Győződjön meg arról, hogy a View az @ScaledMetric-et saját magában használja (nem ViewModel-ben). Ellenőrizze, hogy a View feliratkozott-e a Dynamic Type-ra: az @ScaledMetric automatikusan kiváltja a body frissítést, de ha a View .equatable()-t vagy .id()-t használ, a mechanizmus megszakadhat. Használja az @Environment(\.sizeCategory)-t fallback-ként.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is