重要なポイント
Dynamic TypeはAppleのテクノロジーで、システムテキストサイズが変更されたときにアプリのフォントを自動的にスケーリングします。ユーザーは設定 → アクセシビリティ → ディスプレイとテキストサイズで好みのサイズを設定し、Dynamic Typeをサポートするすべてのアプリが再起動なしでフォントサイズを適応させます。
システムは11のスケーリングレベルを提供します:XS(14ptベース)からXXXL(23ptベース)まで、さらに重度の視覚障害を持つユーザー向けに5つの追加アクセシビリティサイズ(AX1–AX5)があります。サイズが変更されると、iOSはUIContentSizeCategory.didChangeNotificationを生成し、アプリはUIFontMetricsを介してフォントを再読み込みする必要があります。Apple Human Interface Guidelinesによると、Dynamic Typeは行間や文字の比率を変更しません — フォントサイズのみを変更し、すべてのサイズで読みやすさを維持します。
Dynamic Typeはアクセシビリティステータスを目指すアプリに必須です。WWDC 2024で、Appleはダイナミックタイプをサポートしないアプリは、その中核機能がテキストの読み取りに関連する場合、レビューで拒否されるリスクがあると発表しました。IT Sectrのプロジェクトでは、最初のバージョンからDynamic Typeを実装しています — これにより、その後のアクセシビリティ適応にかかる時間を最大20%節約できます。
AppleはシステムフォントSF Pro用にUIFontDescriptor.UIAttributesを介して11の定義済みテキストスタイルを提供しています。開発者はピクセルサイズを指定せず — 意味論的なスタイルを選択し、iOSはユーザーの設定に基づいて実際のフォントサイズを適用します。
| スタイル | サイズ(デフォルト) | サイズ(AX5) | 用途 |
|---|---|---|---|
| .largeTitle | 34pt | 62pt | 第一レベルの画面タイトル |
| .title1 | 28pt | 50pt | 二次見出し |
| .title2 | 22pt | 40pt | セクション見出し |
| .title3 | 20pt | 36pt | 小見出し |
| .headline | 17pt semibold | 31pt | リスト内の強調テキスト |
| .body | 17pt | 31pt | 本文 |
| .callout | 16pt | 29pt | コールアウトと補足テキスト |
| .subheadline | 15pt | 27pt | 要素ラベル |
| .footnote | 13pt | 23pt | 脚注と小文字テキスト |
| .caption1 | 12pt | 21pt | 画像キャプション |
| .caption2 | 11pt | 19pt | ラベルと小さなキャプション |
各スタイルは固定ウェイトのシステムフォントSF Proを使用します(本文はRegular、見出しはBold)。カスタムフォントはUIFontMetricsを介して接続します — サードパーティフォントをダイナミックタイプに適応させる唯一の正しい方法です。
UIFontMetricsはiOS 11で導入されたクラスで、任意のUIFontを選択したテキストスタイルに比例してスケーリングします。iOS 11より前は、開発者はpreferredFontForTextStyleを直接呼び出していましたが、これはシステムフォントSF Proのみを返します。UIFontMetricsはこの問題を解決します:任意のフォントを受け取り、ウェイトとプロポーションを保持したスケーリングバージョンを返します。
scaledFont(for:)メソッドは、ユーザーの現在のテキストサイズに基づいてスケーリング係数を計算します:Largeが選択されている場合、係数は1.0;Very Large(AX1)の場合は約1.3;Maximum(AX5)の場合は最大1.8です。係数はカスタムフォントのベースサイズに適用され、システムフォントには適用されません — これにより、デザイナーの意図がすべてのサイズで維持されます。
UIFontMetricsはアプリ内のすべてのカスタムフォントに推奨されます。WWDC 2024で、AppleはAccessibility Inspectorツールを紹介しました。これはDynamic Typeのサポートをチェックし、UIFontMetricsの代わりに固定フォントサイズを使用する要素をハイライトします。IT Sectrでは、2018年からすべてのプロジェクトでUIFontMetricsを実装しています — これにより、テキストオーバーラップのバグが35%削減されました。
ラベルに動的フォントを設定する最も簡単な方法。コードは、システムテキストサイズの変更に自動的に応答する.bodyスタイルのUILabelの設定方法を示しています。
import UIKit
class GreetingViewController: UIViewController {
private let label: UILabel = {
let l = UILabel()
l.text = "Hello, Dynamic Type!"
l.font = UIFont.preferredFont(forTextStyle: .body)
l.adjustsFontForContentSizeCategory = true
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
adjustsFontForContentSizeCategory = trueフラグは、システムテキストサイズが変更されたときに自動的にフォントを更新します — このフラグがないと、Dynamic Typeは既存のラベルで機能しません。サイズが変更されると、iOSはlayoutIfNeededを呼び出し、ラベルは手動介入なしでフォントを更新します。
カスタムフォント(例:Montserrat)を使用する場合、preferredFontForTextStyleを呼び出すとSF Proが返され、自分のフォントは返されません。UIFontMetricsはカスタムフォントを特異的にスケーリングし、そのデザインを保持します。
import UIKit
extension UIFont {
static func customDynamicFont(name: String,
size: CGFloat,
style: UIFont.TextStyle) -> UIFont {
guard let baseFont = UIFont(name: name, size: size) else {
return .preferredFont(forTextStyle: style)
}
return UIFontMetrics(forTextStyle: style).scaledFont(for: baseFont)
}
}
let titleFont = UIFont.customDynamicFont(
name: "Montserrat-Bold",
size: 20,
style: .title3
)
scaledFont(for:)メソッドはベースUIFontを受け取り、.title3スタイルに比例したスケーリングバージョンを返します。アクセシビリティサイズAX5では、Montserrat-Bold 20ptフォントは約36ptになります — このスタイルのシステムフォントが増加するのとまったく同じ量です。IT Sectrでは、2018年からカスタムフォントを使用するすべてのプロジェクトでこのパターンを使用しており、視覚障害を持つユーザーからの小さなテキストに関する苦情を完全になくしました。
手動でフォントを更新する場合(adjustsFontForContentSizeCategoryなし)、UIContentSizeCategory.didChangeNotification通知を購読します。これは、自動フォント更新を継承しないカスタムUI要素に必要です。
import UIKit
class DynamicLabel: UILabel {
private var customFont: UIFont?
private var textStyle: UIFont.TextStyle = .body
func configure(font: UIFont, style: UIFont.TextStyle) {
customFont = font
textStyle = style
NotificationCenter.default.addObserver(
self,
selector: #selector(updateFont),
name: UIContentSizeCategory.didChangeNotification,
object: nil
)
updateFont()
}
@objc private func updateFont() {
guard let base = customFont else { return }
self.font = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: base)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
didChangeNotificationを購読することで、アプリを再起動せずにシステム設定が変更されるたびにカスタム要素がフォントを更新することが保証されます。iOS 15以降では、Live Text Sizeをサポートするアプリでコントロールセンターからテキストサイズを変更した場合でも通知が届きます。
よくある質問
Dynamic TypeはiOS 7以降で利用可能です。UIFontMetricsはiOS 11で登場しました — それ以前はpreferredFontForTextStyleメソッドが直接使用されていました。iOS 15+では、ダイナミックタイプは大きなフォント用の追加アクセシビリティサイズ(AX1–AX5)をサポートしています。iOS 10以下をサポートするアプリはUIFontMetricsなしでpreferredFontForTextStyleを使用し、サポートがシステムフォントSF Proのみに制限されます。
Xcode 15+で、シミュレーターを開き、設定 → アクセシビリティ → ディスプレイとテキストサイズ → 大きいテキストに移動します。スライダーをドラッグしてサイズを変更します。Xcode自体にはDebug → Accessibility Inspectorがあり、固定フォントの要素をハイライトします。自動化には、XCUITestを介してUISlider設定を変更するテストを使用します — これにより、すべての画面が正しく再構築されることが保証されます。
はい、ダイナミックタイプでのAuto Layoutは、UILabelとUIButtonでintrinsicContentSizeを使用する必要があります。アクセシビリティサイズでは、テキストがsuperviewの境界を超える可能性があります — UIScrollViewを追加するか、leading/trailing制約を増やしてください。パディングにはUIFontMetrics.scaledValueを使用し、文字間隔もフォントに比例してスケーリングされるようにします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。