Menambahkan Pengetikan Kustom Dinamis ke Proyek iOS Anda — Nimble

pengantar
Dynamic Type
adalah fitur aksesibilitas di iOS dan macOS. Fitur tersebut memungkinkan pengguna untuk mengatur skala teks yang diterapkan ke seluruh perangkat, diperbarui secara otomatis. Skala bisa lebih besar dari default untuk membantu pengguna dengan kemampuan penglihatan yang lebih rendah atau lebih kecil untuk mengisi layar dengan lebih banyak data sekaligus.

Font default UIKit dan SwiftUI menyertakan fitur ini secara internal, yang harus dilakukan pengembang hanyalah mengatur font pada label dengan gaya font.
textLabel.font = .preferredFont(forTextStyle: .body)

Menambahkan Font Kustom
Mulailah dengan memilih font yang akan digunakan dalam proyek. Dianjurkan untuk menggunakan font dengan banyak bobot untuk menyampaikan makna yang berbeda dalam aplikasi.
Font dapat diunduh dari platform gratis seperti Google Fonts .
Seret file font ke proyek Xcode. Praktik terbaiknya adalah membuat folder Font
dan subfolder untuk setiap jenis font.

Buka target utama Info.plist
dan tambahkan kunci UIAppFonts
sebagai larik. Di dalam array, tambahkan nama file dan ekstensi untuk setiap font yang disertakan.

File font sekarang diimpor ke proyek dan dapat digunakan dengan membuat instance UIFont.
textLabel.font = UIFont(name: "Font-Name", size: UIFont.labelFontSize)
for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
print("Family: \(family) Font names: \(names)")
}
// Family: Zen Old Mincho Font names: ["ZenOldMincho-Regular", "ZenOldMincho-Bold"]
Cara termudah untuk menggunakan font khusus di proyek Swift adalah dengan menetapkan font langsung ke label.
textLabel.font = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)
Menyesuaikan Ukuran Teks di iOS
Pengaturan Aksesibilitas
Luncurkan aplikasi Pengaturan di perangkat atau simulator. Arahkan ke Accessibility > Display & Text Size > Larger Text
. Penggeser akan mengubah ukuran font untuk sistem.

Mengubah ukuran teks tidak akan menyebabkan aplikasi apa pun diluncurkan tetapi tata letaknya akan dibuat ulang.
⚙️ Ini untuk iOS 15, versi iOS lainnya akan memiliki sedikit perbedaan tetapi opsi harus dapat dicari dengan Text Size
atau Larger Text
.
Penggantian Lingkungan Xcode
Di Xcode, setelah berhasil menjalankan aplikasi di simulator, temukan file Debug Area
. Itu Debug Area
berisi tombol dengan simbol matikan. Tombol ini akan memunculkan Environment Overrides
menu untuk simulator. Ukuran teks dapat disesuaikan dengan penggeser untuk Dynamic Type
.

Environment Overrides
akan mengesampingkan pengaturan simulator dan akan mengembalikan pengaturan terbaru pada simulator saat dimatikan.
Meluncurkan ulang aplikasi dengan pengaturan perangkat yang diubah harus menampilkan teks baru dalam skala baru. Namun, ukuran font tidak dapat diubah saat aplikasi sedang berjalan. Apa yang hilang adalah alat penskalaan. Ubah kode untuk menyetel teks label sebagai berikut:
let customFont = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)!
label.font = UIFontMetrics.default.scaledFont(for: customFont)
label.adjustsFontForContentSizeCategory = true
Untuk meningkatkan UIFontMetrics
kemampuan, kami memperkenalkan pembantu:
func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont?
Selain menambahkan layer lain ke UIFontMetrics
, helper berfungsi sebagai gateway untuk fungsionalitas yang dapat dilakukan aplikasi. Daftar persyaratan tersebut meliputi:
- Semua font khusus dapat digunakan dalam satu fungsi.
- Ukuran teks dapat dibedakan berdasarkan gaya teksnya (yaitu: badan, judul, keterangan, dll.).
- Ukuran teks dapat diganti dengan pengaturan dalam aplikasi.
Pertama, kami membuat protokol untuk memilih font: DynamicFont
.
protocol DynamicFont {
func fontName() -> String
func fontSize(style: UIFont.TextStyle) -> CGFloat
}
Contoh DynamicFont
untuk demo kami adalah sebagai berikut.
enum ZenOldMincho: DynamicFont {
case regular
case bold
func fontName() -> String {
switch self {
case .regular: return "ZenOldMincho-Regular"
case .bold: return "ZenOldMincho-Bold"
}
}
func fontSize(style: UIFont.TextStyle) -> CGFloat {
switch style {
case .largeTitle: return 34.0
case .title1: return 28.0
case .title2: return 22.0
case .title3: return 20.0
case .headline: return 18.0
case .body: return 17.0
case .callout: return 16.0
case .subheadline: return 15.0
case .footnote: return 13.0
case .caption1: return 12.0
case .caption2: return 11.0
default: return 17.0
}
}
}
extension UIFont {
static func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont? {
guard let customFont = UIFont(name: font.fontName(), size: font.fontSize(style: style)) else { return nil }
let scaledFont: UIFont
let metrics = UIFontMetrics(forTextStyle: style)
return scaledFont = metrics.scaledFont(
for: customFont, compatibleWith: UITraitCollection(
preferredContentSizeCategory: overrideFontSize ?? .unspecified
)
)
}
}
textLabel.font = .customFont(ZenOldMincho.regular, forTextStyle: .body)
overridedLabel.font = .customFont(ZenOldMincho.bold, forTextStyle: .headline, overrideFontSize: .small)
Versi helper di atas dapat langsung digunakan di iOS 11. UILabel
harus adjustsFontForContentSizeCategory
diatur true
untuk mengizinkan pembaruan otomatis saat sistem mengubah ukuran teks.
label.adjustsFontForContentSizeCategory = true
label.font = .customFont(ZenOldMincho.regular, forTextStyle: .body)
label.adjustsFontForContentSizeCategory = false
label.font = .customFont(ZenOldMincho.regular, forTextStyle: .body, overrideFontSize: .small)
iOS 10
UIFontMetrics.scaledFont
hanya tersedia di iOS 11 dan lebih baru. Untuk iOS 10, skala font perlu disediakan secara manual untuk setiap kategori gaya dan ukuran teks, serta memperbarui font saat ukuran teks sistem berubah.
Skala Huruf
Perkenalkan protokol baru:
protocol DynamicFontIOS10 {
func font(for style: UIFont.TextStyle, sizeCategory: UIContentSizeCategory) -> UIFont?
}
extension ZenOldMincho: DynamicFontIOS10 {
func font(for style: UIFont.TextStyle, sizeCategory: UIContentSizeCategory) -> UIFont? {
guard let style = ZenOldMincho.fontSizeTable[style],
let size = style[sizeCategory]
else { return nil }
return UIFont(name: fontName(), size: size)
}
}
extension ZenOldMincho {
static let fontSizeTable: [UIFont.TextStyle: [UIContentSizeCategory: CGFloat]] = [
.headline: [
.accessibilityExtraExtraExtraLarge: 23.0,
.accessibilityExtraExtraLarge: 23.0,
.accessibilityExtraLarge: 23.0,
.accessibilityLarge: 23.0,
.accessibilityMedium: 23.0,
.extraExtraExtraLarge: 23.0,
.extraExtraLarge: 21.0,
.extraLarge: 19.0,
.large: 17.0,
.medium: 16.0,
.small: 15.0,
.extraSmall: 14.0
],
.body: [
.accessibilityExtraExtraExtraLarge: 53.0,
.accessibilityExtraExtraLarge: 47.0,
.accessibilityExtraLarge: 40.0,
.accessibilityLarge: 33.0,
.accessibilityMedium: 28.0,
.extraExtraExtraLarge: 23.0,
.extraExtraLarge: 21.0,
.extraLarge: 19.0,
.large: 17.0,
.medium: 16.0,
.small: 15.0,
.extraSmall: 14.0
]
// Fill with all text style
}
Fungsi ini customFont
perlu dimodifikasi untuk mengakomodasi penskalaan iOS 10.
static func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont? {
guard let customFont = UIFont(name: font.fontName(), size: font.fontSize(style: style)) else { return nil }
let scaledFont: UIFont
if #available(iOS 11.0, *) {
let metrics = UIFontMetrics(forTextStyle: style)
scaledFont = metrics.scaledFont(
for: customFont, compatibleWith: UITraitCollection(
preferredContentSizeCategory: overrideFontSize ?? .unspecified
)
)
} else {
let sizeCategory = overrideFontSize ?? UIApplication.shared.preferredContentSizeCategory
guard let fontIOS10 = font as? DynamicFontIOS10,
let customFontIOS10 = fontIOS10.font(for: style, sizeCategory: sizeCategory)
else { return customFont }
scaledFont = customFontIOS10
}
return scaledFont
}
Perbarui Ukuran Teks Secara Otomatis
Saat ini, aplikasi hanya akan menampilkan font yang benar saat pertama kali dimuat. Halaman perlu mengatur font untuk setiap komponen setiap kali ukuran teks berubah. Hal ini dapat dilakukan dengan mendengarkan NotificationCenter
notifikasi UIContentSizeCategory.didChangeNotification
.
protocol DynamicFontController {
func setUpContentSizeNotification(disposeBag: DisposeBag)
func updateFonts(notification: Notification)
}
extension DynamicFontController where Self: UIViewController {
func setUpContentSizeNotification(disposeBag: DisposeBag) {
NotificationCenter.default.rx.notification(UIContentSizeCategory.didChangeNotification, object: nil)
.withUnretained(self)
.take(until: rx.deallocated)
.subscribe { owner, value in
owner.updateFonts(notification: value)
}
.disposed(by: disposeBag)
}
}
Untuk yang non RxSwift
, jangan lupa NotificationCenter.removeObserver
hubungi deinit
.
Ukuran font akan diperbarui secara otomatis saat ukuran teks sistem berubah.
SwiftUI
SwiftUI memiliki pengubah tampilan khusus untuk memodifikasi font.
.font(.custom(name, size: size))
Text("Hello").font(.custom("ZenOldMincho-Regular", size: 16.0))
Memperbarui Ukuran Font
Untuk mengizinkan pembaruan ukuran font, pengubah tampilan baru akan digunakan untuk memperhitungkan perubahan ukuran teks sistem.
Jika proyek tersebut murni SwiftUI, deklarasi yang ada customFont(_ font: DynamicFont, forTextStyle style: UIFont.TextStyle, overrideFontSize: UIContentSizeCategory? = nil) -> UIFont?
dapat diabaikan.
Deklarasi metode SwiftUI yang setara adalah:
extension View {
func scaledFont(
font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: ContentSizeCategory? = nil
) -> some View {
return modifier(
ScaledFont(
name: font.fontName(),
size: font.fontSize(style: style),
overrideFontSize: overrideFontSize
)
)
}
}
Deklarasi ScaledFont
adalah:
struct ScaledFont: ViewModifier {
@Environment(\.sizeCategory) var sizeCategory
var name: String
var size: CGFloat
var overrideFontSize: ContentSizeCategory?
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size)
return content.font(.custom(name, size: scaledSize))
}
}
Dengan pengubah scaledFont
kita dapat mengubah font pada tampilan apa pun dengan tanda tangan yang serupa. Tampilan yang dihasilkan akan memperbarui ukuran font saat pengaturan sistem berubah.
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline)
Implementasi saat ini ScaledFont: ViewModifier
tidak termasuk mengesampingkan ukuran font dalam aplikasi.
Untuk mengizinkan pengesampingan, UIFontMetrics.scaledValue(for:, compatibleWith:)
akan digunakan. Ini sama dalam UIKit
implementasinya; namun, mengonversi dari ContentSizeCategory
ke UIContentSizeCategory
, untuk memenuhi scaledValue
input , hanya dapat dilakukan untuk iOS 14 dan yang lebih baru.
Ubah kode untuk ScaledFont.body
menjadi:
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size, compatibleWith: UITraitCollection(
preferredContentSizeCategory: UIContentSizeCategory(overrideFontSize)
))
return content.font(.custom(name, size: scaledSize))
}
Dengan menggunakan modifier scaledFont
, kita sekarang dapat mengganti ukuran teks.
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline, overrideFontSize: .extraLarge)
Swift terus berkembang untuk memungkinkan penerapan aksesibilitas yang mudah guna meningkatkan kualitas hidup pengguna. Fungsi pembantu yang disajikan di blog ini dapat dengan mudah diintegrasikan ke dalam proyek yang sudah ada dan yang baru.
Font Dinamis akan memungkinkan pengguna yang kuat untuk melihat lebih banyak data dengan sekilas serta membantu pengguna dengan masalah penglihatan untuk menggunakan aplikasi dengan lancar. Font Dinamis adalah salah satu dari banyak fitur aksesibilitas yang dapat digunakan pengembang untuk meningkatkan aplikasi mereka.
Kode sumber untuk proyek ini tersedia di repositori kami .
Referensi
Menskalakan font kustom secara otomatis dengan Tipe Dinamis Cara menggunakan Tipe Dinamis dengan font kustom Tipe Dinamis Praktis
Awalnya diterbitkan di https://nimblehq.co .