Published on

Swift-da Accessibility β€” Dynamic Text (dinamik matn o'lchami)

Authors

Accessibility nima va nima uchun muhim

Accessibility β€” bu ilovangizni barcha foydalanuvchilar, jumladan maxsus ehtiyojlilari uchun foydalanish mumkin qilish. Bu, qonun bilan ham talablanadi.

Bu videoda β€” Dynamic Text (dinamik matn): foydalanuvchi telefon sozlamalarida matn o'lchamini o'zgartirsa, ilovangiz shunga mos ravishda moslashishi kerak.

Dynamic Type-dan foydalanadigan foydalanuvchilar soni kutilgandan ancha ko'p β€” uni qo'llab-quvvatlash barchasi quradigan ilovaning bir qismi bo'lishi kerak.


Oddiy misol β€” boshlang'ich view

NavigationStack {
    List {
        ForEach(0..<10) { _ in
            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Image(systemName: "heart.fill")
                    Text("Welcome to my app")
                        .font(.title)
                }

                Text("This is some longer text that expands to multiple lines")
                    .font(.subheadline)
            }
        }
    }
    .listStyle(.plain)
    .navigationTitle("Hello world")
}

Dynamic Type simulatorda sinash

Xcode-da simulatorning pastidagi Device Settings β†’ Dynamic Type ni yoqish orqali turli o'lchamlarni ko'rish mumkin. O'lchamlar: Extra Small β†’ ... β†’ Accessibility 1 β†’ ... β†’ Accessibility 5.

Eng muhim qoida: doim eng kichik qurilmada va eng katta Dynamic Type bilan sinang β€” bu eng qiyin holat (worst case).


Muammo 1: Qattiq balandlik (fixed height)

VStack { ... }
    .frame(height: 100)           // ← MUAMMO
    .frame(maxWidth: .infinity, alignment: .leading)
    .background(Color.red)

Bu kod, kichik o'lchamda yaxshi ko'rinadi. Ammo Dynamic Type kattalashtirilganda, matn qisqartirib ko'rsatiladi (ellipsis) β€” chunki frame-ning balandligi 100da "qotib qolgan".

Yechim: Fixed height-ni olib tashlash

VStack { ... }
    // .frame(height: 100)        // ← O'chirildi
    .frame(maxWidth: .infinity, alignment: .leading)
    .background(Color.red)

Fixed balandlik o'chirilganda β€” matn keraklicha kengayadi. Imkon qadar maxWidth, maxHeight, padding va spacing ishlatilsin β€” qattiq o'lchamlar emas.


truncationMode β€” ellipsis joylashuvi

Agar matn qisqartirib ko'rsatilishi kerak bo'lsa, ellipsis qayerda ko'rinishini sozlash mumkin:

Text("This is some longer text...")
    .truncationMode(.head)    // ... boshda
    .truncationMode(.middle)  // ... o'rtada
    .truncationMode(.tail)    // ... oxirida (standart)

lineLimit β€” qator sonini cheklash

Matn juda kengayib ketmasligi uchun, maksimal qator sonini belgilash mumkin:

Text("This is some longer text that expands to multiple lines")
    .font(.subheadline)
    .lineLimit(3)

lineLimit(nil) β€” cheklanmagan (standart). lineLimit(3) β€” maksimal 3 qator.


minimumScaleFactor β€” matnni kichraytirish

lineLimit bilan birgalikda, matnni belgilangan qatorga sig'dirish uchun, kichikroq qilib ko'rsatish mumkin:

Text("This is some longer text...")
    .font(.subheadline)
    .lineLimit(3)
    .minimumScaleFactor(0.8)
  • 1.0 β€” hech qachon kichraytirmaydi (standart)
  • 0.8 β€” joriy o'lchamning 80% gacha kichraytirishi mumkin
  • 0.5 β€” joriy o'lchamning 50% gacha kichraytirishi mumkin

Muhim ogohlantirish

Foydalanuvchi Dynamic Type-ni ko'rish muammosi tufayli kattalashtirgan bo'lsa, va bizning kod uni yana kichraytirsa β€” bu accessibility-ning maqsadiga ziddir. Shuning uchun:

  • minimumScaleFactor-ni juda past qo'ymang
  • 0.8–0.9 β€” odatda yaxshi muvozanat
  • Imkon qadar, matnni kichraytirish o'rniga β€” matn kengayishiga ruxsat bering

ContentSizeCategory β€” environment o'zgaruvchisi

Joriy Dynamic Type o'lchamini kod ichida bilish uchun:

@Environment(\.sizeCategory) var sizeCategory

Bu β€” ContentSizeCategory tipidagi enum:

.extraSmall
.small
.medium
.large              ← standart o'lcham
.extraLarge
.extraExtraLarge
.extraExtraExtraLarge
.accessibilityMedium
.accessibilityLarge
.accessibilityExtraLarge
.accessibilityExtraExtraLarge
.accessibilityExtraExtraExtraLarge

Foydalanish misoli

@Environment(\.sizeCategory) var sizeCategory

var body: some View {
    Text("This is some longer text...")
        .font(.subheadline)
        .lineLimit(3)
        .minimumScaleFactor(
            sizeCategory == .accessibilityExtraExtraLarge ? 0.8 : 1.0
        )
}

Extension β€” turli o'lchamlar uchun turli minimumScaleFactor

Bitta if ifodasi barcha holatlerni qamrab olmaydi. Extension yordamida aniqroq yondashish mumkin:

extension ContentSizeCategory {
    var customMinScaleFactor: CGFloat {
        switch self {
        case .extraSmall, .small, .medium:
            return 1.0       // Kichik o'lchamlar β€” kichraytirish shart emas
        case .large, .extraLarge, .extraExtraLarge:
            return 0.8       // Biroz kichraytirish mumkin
        default:
            return 0.6       // Eng katta o'lchamlar β€” ko'proq kichraytirish mumkin
        }
    }
}

Ishlatish

@Environment(\.sizeCategory) var sizeCategory

Text("This is some longer text...")
    .font(.subheadline)
    .lineLimit(3)
    .minimumScaleFactor(sizeCategory.customMinScaleFactor)

Endi minimumScaleFactor foydalanuvchining Dynamic Type o'lchamiga qarab avtomatik moslashadi.


Dynamic Type Variants β€” preview

Xcode-ning eng foydali accessibility xususiyati: preview-da pastki o'ng burchakdagi Variants tugmasi β†’ Dynamic Type Variants.

Bu β€” barcha Dynamic Type o'lchamlarini bir vaqtda ko'rsatadi (Extra Small dan Accessibility 5 gacha). Ilovani har safar qayta ishga tushirmasdan, real vaqtda barcha o'lchamlarda qanday ko'rinishini ko'rish mumkin.

Tavsiya etilgan ish jarayoni:

  1. Ekranni qurib, Dynamic Type Variants-ni oching
  2. Eng katta o'lchamdan boshlang
  3. Fixed frame-larni olib tashlang
  4. lineLimit qo'shing
  5. Zarur bo'lsa β€” minimumScaleFactor qo'shing
  6. Yuqoriga ko'tarilib, kichik o'lchamlarni ham tekshiring

Sistema ikonkalar (SF Symbols) β€” o'lchami

Sistema ikonkalar (SF Symbols) standart holatda Dynamic Type bilan birga avtomatik kengayadi:

// Dinamik β€” Dynamic Type bilan kengayadi (standart xulq)
Image(systemName: "heart.fill")
    .font(.headline)

// Qattiq o'lcham β€” hech qachon o'zgarmaydi
Image(systemName: "heart.fill")
    .font(.system(size: 20))

Xuddi shunday matn uchun:

// Dinamik β€” Dynamic Type bilan kengayadi
Text("Hello")
    .font(.subheadline)

// Qattiq o'lcham β€” hech qachon o'zgarmaydi
Text("Hello")
    .font(.system(size: 20))

Qattiq o'lchamlar β€” faqat juda maxsus UI holatlarida. Odatda dinamik shrift ishlatilsin, chunki biz accessibility-ni qo'llab-quvvatlashni xohlaymiz.


Xulosa β€” amaliy qoida

MuammoYechim
Fixed height/widthOlib tashlash β†’ maxWidth/maxHeight
Matn qisqartiriladilineLimit qo'shish
Juda kengayib ketadilineLimit + minimumScaleFactor(0.8)
Har bir o'lcham uchun turli shkalaContentSizeCategory extension
Barcha o'lchamlarni bir vaqtda tekshirishXcode β†’ Variants β†’ Dynamic Type Variants

Shaxsiy ish jarayonim:

  1. Fixed o'lchamlardan qoching
  2. Ekranni qurib bo'lgach, Dynamic Type Variants-ni oching
  3. Eng pastga (eng katta o'lcham) turib boshlang
  4. Fixed frame-larni olib tashlang β†’ lineLimit qo'shing β†’ kerak bo'lsa minimumScaleFactor
  5. Bu qadamlar bajarilganda, ko'pchilik ekranlar accessibility uchun tayyor
Buy mea coffee