SwiftUI: sovrascrive il carattere di sistema con più stili

Aug 22 2020

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 UIFonts 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 titledimensione.

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 Viewusasse 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

5 LuLuGaGa Aug 22 2020 at 17:49

Puoi iniziare a definire un'abitudine ViewModifierper 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.TextStylecome .title, .bodyo definirne di propri come .pricenell'esempio precedente.

Per ogni caso TextStyledevi dichiarare il nome del font e la sua dimensione predefinita. Se includi sizeCategorycome nel mio esempio, il carattere si adatterebbe al tipo dinamico.

Puoi anche definire un'estensione su Viewper 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 Textsenza 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)
    }
    
}
2 MahdiBM Aug 22 2020 at 04:08

È 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))