SwiftUI: sovrascrive il carattere di sistema con più stili
Quindi SwiftUI ci offre una bella .font()
estensione che ci consente di impostare la dimensione del carattere, lo stile, il peso, ecc. Del testo. Questo rispecchia bene gli attributi dei caratteri CSS e viene fornito anche con simpatiche scorciatoie come .font(.title)
, .font(.body)
, .font(.caption)
.
I CSS brillano quando si tratta di caratteri personalizzati, permettendoci di importare caratteri da uno o più file che definiscono collettivamente diversi pesi e stili all'interno della stessa famiglia. Puoi quindi utilizzare quel carattere ovunque automaticamente dichiarando una famiglia di caratteri al livello superiore del documento, quindi tutte le dichiarazioni di carattere utilizzeranno automaticamente quel carattere.
iOS ci consente di importare caratteri personalizzati, ma sembra non essere all'altezza quando si tratta di utilizzarli . Sto cercando un modo per iOS di rispecchiare il comportamento dei CSS.
Ho 10 file di font per una singola famiglia di font: 5 pesi diversi (leggero, normale, semi-grassetto, grassetto ed extra-grassetto) ciascuno con uno stile regolare e corsivo. Sono in grado di creare un'istanza di UIFont
s per questi caratteri, ma sto cercando un modo per impostare questa famiglia di caratteri a livello globale in modo da poter dichiarare .font(.title, weight: .bold)
e fare in modo che utilizzi implicitamente la variante in grassetto della mia famiglia di caratteri con la title
dimensione.
Sono a conoscenza dei modi per sovrascrivere globalmente il carattere, ma sto specificamente cercando un modo per utilizzare più caratteri della stessa famiglia per avere funzionalità automatiche in grassetto e corsivo. Se esiste un bel modo SwiftUI per farlo, sarebbe preferibile, ma anche una soluzione UIKit va bene.
EDIT: Un'altra cosa che avrei dovuto menzionare è che vorrei che il carattere predefinito di ognuno View
usasse il mio carattere anche senza .font()
modificatore. Quindi se ho
Text("Hello, world")
dovrebbe usare il mio carattere con il peso e la dimensione predefiniti (penso che sia .body
).
Risposte
Puoi iniziare a definire un'abitudine ViewModifier
per gestire la logica della scelta del tipo e della dimensione corretti di un font:
struct MyFont: ViewModifier {
@Environment(\.sizeCategory) var sizeCategory
public enum TextStyle {
case title
case body
case price
}
var textStyle: TextStyle
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size)
return content.font(.custom(fontName, size: scaledSize))
}
private var fontName: String {
switch textStyle {
case .title:
return "TitleFont-oBld"
case .body:
return "MyCustomFont-Regular"
case .price:
return "MyCustomFont-Mono"
}
}
private var size: CGFloat {
switch textStyle {
case .title:
return 26
case .body:
return 16
case .price:
return 14
}
}
}
Al suo interno definisci un'enumerazione per tutti gli stili di testo che desideri riutilizzare nella tua app. È possibile utilizzare gli stessi nomi di nativi Font.TextStyle
come .title
, .body
o definirne di propri come .price
nell'esempio precedente.
Per ogni caso TextStyle
devi dichiarare il nome del font e la sua dimensione predefinita. Se includi sizeCategory
come nel mio esempio, il carattere si adatterebbe al tipo dinamico.
Puoi anche definire un'estensione su View
per poter applicare questo modificatore allo stesso modo del native font(_ font: Font?)
.
extension View {
func myFont(_ textStyle: MyFont.TextStyle) -> some View {
self.modifier(MyFont(textStyle: textStyle))
}
}
Ora puoi applicarlo in questo modo:
Text("Any text will do").myFont(.title)
Text("£3.99").myFont(.price)
Per l'impostazione predefinita Text
senza un modificatore applicato puoi utilizzare la soluzione di Mahdi BM o definire il tuo tipo:
struct MyText: View {
let text: String
init(_ text: String) {
self.text = text
}
var body: some View {
Text(text).myFont(.body)
}
}
È possibile sovrascrivere il carattere dell'ambiente predefinito del sistema utilizzando un .environment()
modificatore in cima a una vista. puoi usarlo sopra la tua prima vista in modo che venga applicato a tutte le tue viste.
.environment(\.font, .custom("Your_Font_Name", size: theFontSizeYouPrefer))