Ajout de la saisie personnalisée dynamique à votre projet iOS — Nimble

Introduction
Dynamic Type
est une fonctionnalité d'accessibilité sur iOS et macOS. La fonctionnalité permet à l'utilisateur de définir une échelle de texte appliquée à l'ensemble de l'appareil, mise à jour automatiquement. L'échelle peut être plus grande que la valeur par défaut pour aider les utilisateurs ayant une capacité de vision réduite ou plus petite pour remplir l'écran avec plus de données à la fois.

La police par défaut de UIKit et SwiftUI inclut cette fonctionnalité en interne, tout ce que le développeur a à faire est de définir la police sur l'étiquette avec un style de police.
textLabel.font = .preferredFont(forTextStyle: .body)

Ajout d'une police personnalisée
Commencez par choisir une police à utiliser dans le projet. Il est conseillé d'utiliser une police avec plusieurs poids pour transmettre différentes significations dans l'application.
Les polices peuvent être téléchargées à partir d'une plateforme gratuite telle que Google Fonts .
Faites glisser les fichiers de police vers le projet Xcode. La meilleure pratique consiste à créer un dossier Font
et un sous-dossier pour chaque famille de polices.

Ouvrez la cible principale Info.plist
et ajoutez la clé UIAppFonts
en tant que tableau. À l'intérieur du tableau, ajoutez le nom de fichier et l'extension de chacune des polices incluses.

Les fichiers de police sont maintenant importés dans le projet et peuvent être utilisés en créant une instance de 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"]
Le moyen le plus simple d'utiliser une police personnalisée dans le projet Swift consiste à attribuer la police directement à l'étiquette.
textLabel.font = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)
Ajuster la taille du texte sur iOS
Paramètres d'accessibilité
Lancez l'application Paramètres sur l'appareil ou un simulateur. Accédez à Accessibility > Display & Text Size > Larger Text
. Le curseur changera la taille de la police pour le système.

La modification de la taille du texte ne provoquera le lancement d'aucune application, mais la mise en page sera refaite.
⚙️ Ceci est pour iOS 15, les autres versions d'iOS auront une légère différence mais l'option devrait être consultable avec Text Size
ou Larger Text
.
Remplacements de l'environnement Xcode
Sur Xcode, après avoir exécuté avec succès l'application sur un simulateur, recherchez le fichier Debug Area
. Le Debug Area
contient un bouton avec le symbole de bascule. Ce bouton devrait faire apparaître le Environment Overrides
menu du simulateur. La taille du texte peut être ajustée avec le curseur pour Dynamic Type
.

Environment Overrides
remplacera les paramètres du simulateur et renverra les paramètres les plus récents sur le simulateur lorsqu'il est éteint.
La relance de l'application avec les paramètres de l'appareil modifiés devrait afficher le nouveau texte dans la nouvelle échelle. Cependant, il n'est pas possible de modifier la taille de la police lorsque l'application est en cours d'exécution. Ce qui manque, c'est un outil de mise à l'échelle. Modifiez le code de définition du texte de l'étiquette comme suit :
let customFont = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)!
label.font = UIFontMetrics.default.scaledFont(for: customFont)
label.adjustsFontForContentSizeCategory = true
Pour tirer parti UIFontMetrics
des capacités, nous introduisons un assistant :
func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont?
En plus d'ajouter une autre couche à UIFontMetrics
, l'assistant sert de passerelle pour les fonctionnalités que l'application peut faire. La liste des exigences comprend :
- Toutes les polices personnalisées peuvent être utilisées dans une seule fonction.
- Les tailles de texte se distinguent par leur style de texte (c'est-à-dire : corps, titre, légende, etc.).
- La taille du texte peut être remplacée par les paramètres de l'application.
Tout d'abord, nous créons un protocole pour choisir une police : DynamicFont
.
protocol DynamicFont {
func fontName() -> String
func fontSize(style: UIFont.TextStyle) -> CGFloat
}
L'exemple de DynamicFont
notre démo est le suivant.
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)
La version ci-dessus de l'assistant peut être utilisée immédiatement sur iOS 11. UILabel
devrait être adjustsFontForContentSizeCategory
définie true
pour autoriser les mises à jour automatiques lorsque le système modifie la taille du texte.
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
est uniquement disponible sur iOS 11 et versions ultérieures. Pour iOS 10, l'échelle de la police devra être fournie manuellement pour chaque style de texte et catégorie de taille, ainsi que la mise à jour de la police lorsque la taille du texte du système change.
Échelle de la police
Introduire un nouveau protocole :
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
}
La fonction customFont
devra être modifiée pour s'adapter aux mises à l'échelle d'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
}
Mettre à jour automatiquement la taille du texte
Actuellement, l'application n'affichera la police correcte que lorsqu'elle sera chargée pour la première fois. La page devra définir la police pour chaque composant chaque fois que la taille du texte change. Cela peut être fait en écoutant la NotificationCenter
notification de 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)
}
}
Pour un non RxSwift
, n'oubliez pas d'appeler NotificationCenter.removeObserver
le deinit
.
La taille de la police sera mise à jour automatiquement lorsque la taille du texte du système changera.
SwiftUI
SwiftUI a un modificateur de vue spécifiquement pour modifier la police.
.font(.custom(name, size: size))
Text("Hello").font(.custom("ZenOldMincho-Regular", size: 16.0))
Mise à jour de la taille de la police
Pour permettre la mise à jour de la taille de la police, un nouveau modificateur de vue sera utilisé pour tenir compte du changement de la taille du texte du système.
Si le projet est purement SwiftUI, la déclaration existante de customFont(_ font: DynamicFont, forTextStyle style: UIFont.TextStyle, overrideFontSize: UIContentSizeCategory? = nil) -> UIFont?
peut être ignorée.
La déclaration d'une méthode SwiftUI équivalente est :
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
)
)
}
}
La déclaration de ScaledFont
est :
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))
}
}
Avec le modificateur, scaledFont
nous pouvons changer la police sur n'importe quelle vue avec une signature similaire. La vue résultante mettra à jour la taille de la police à mesure que les paramètres du système changent.
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline)
L'implémentation actuelle de ScaledFont: ViewModifier
n'inclut pas le remplacement de la taille de la police dans l'application.
Pour autoriser le remplacement, UIFontMetrics.scaledValue(for:, compatibleWith:)
sera utilisé. C'est la même chose dans UIKit
la mise en œuvre; cependant, la conversion de ContentSizeCategory
vers UIContentSizeCategory
, pour satisfaire scaledValue
l'entrée de , n'est possible que pour iOS 14 et supérieur.
Modifiez le code pourScaledFont.body
:
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))
}
En utilisant le modificateur scaledFont
, nous pouvons maintenant remplacer la taille du texte.
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline, overrideFontSize: .extraLarge)
Swift évolue en permanence pour permettre une mise en œuvre facile de l'accessibilité afin d'améliorer la qualité de vie des utilisateurs. Les fonctions d'assistance présentées dans ce blog peuvent être facilement intégrées dans des projets existants et nouveaux.
Dynamic Font permettra aux utilisateurs expérimentés de voir plus de données d'un coup d'œil et aidera les utilisateurs ayant des problèmes de vision à utiliser l'application en douceur. Dynamic Font est l'une des nombreuses fonctionnalités d'accessibilité que les développeurs peuvent adopter pour améliorer leurs applications.
Le code source de ce projet est disponible sur notre dépôt .
Références
Mise à l'échelle automatique des polices personnalisées avec Dynamic Type Comment utiliser Dynamic Type avec une police personnalisée Type dynamique pratique
Publié à l'origine sur https://nimblehq.co .