SwiftUI-システムフォントを複数のスタイルで上書きする

Aug 22 2020

したがって、SwiftUIは.font()、テキストのフォントサイズ、スタイル、太さなどを設定できる優れた拡張機能を提供します。このミラーのCSSのフォントがうまく属性、およびさえのような素敵な速記が付属しています.font(.title).font(.body).font(.caption)

CSSは、カスタムフォントに関しては優れており、同じファミリ内の複数のウェイトとスタイルをまとめて定義する1つ以上のファイルからフォント面をインポートできます。次に、ドキュメントのトップレベルでフォントファミリを宣言することにより、そのフォントをどこでも自動的に使用できます。その後、すべてのフォント宣言でそのフォントが自動的に使用されます。

iOSではカスタムフォントをインポートできますが、それらの使用に関しては不十分なようです。iOSがCSSの動作を反映する方法を探しています。

1つのフォントファミリに10個のフォントファイルがあります。それぞれが通常の斜体スタイルの5つの異なる太さ(ライト、レギュラー、セミボールド、ボールド、エクストラボールド)です。UIFontこれらのフォントのをインスタンス化することはできますが、このフォントファミリーをグローバルに設定して.font(.title, weight: .bold)、フォントファミリーの太字のバリアントをtitleサイズとともに宣言し、暗黙的に使用できるようにする方法を探しています。

フォントをグローバルにオーバーライドする方法を知っていますが、同じファミリの複数のフォントを使用して、自動的に太字と斜体の機能を使用する方法を特に探しています。これを行うための優れたSwiftUIの方法がある場合は、それが推奨されますが、UIKitソリューションも問題ありません。

編集:私が言及すべきもう一つのことは、すべてのデフォルトフォントが修飾子Viewなしでも私のフォントを使用することを望んでいるということです.font()。だから私が持っているなら

Text("Hello, world")

デフォルトの太さとサイズで私のフォントを使用する必要があります(これはそうだと思います.body)。

回答

5 LuLuGaGa Aug 22 2020 at 17:49

ViewModifierフォントの適切なタイプとサイズを選択するロジックを処理するカスタムの定義を開始できます。

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

その中で、アプリ全体で再利用するすべてのテキストスタイルの列挙型を定義します。あなたはネイティブと同じ名前を使用することができるFont.TextStyleような.title.bodyまたはのような独自の定義.price上記の例では。

いずれの場合もTextStyle、フォントの名前とデフォルトのサイズを宣言する必要があります。sizeCategory私の例のように含めると、フォントは動的タイプに適応します。

に拡張機能を定義しViewて、ネイティブと同じ方法でこの修飾子を適用できるようにすることもできますfont(_ font: Font?)

extension View {
    
    func myFont(_ textStyle: MyFont.TextStyle) -> some View {
        self.modifier(MyFont(textStyle: textStyle))
    }
}

これで、次のように適用できます。

Text("Any text will do").myFont(.title)
Text("£3.99").myFont(.price)

Text修飾子が適用されていないデフォルトの場合、Mahdi BMのソリューションを使用するか、独自のタイプを定義できます。

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

.environment()ビューの上に修飾子を使用すると、システムのデフォルトの環境フォントを上書きできます。最初のビューの上で使用できるため、すべてのビューに適用されます。

.environment(\.font, .custom("Your_Font_Name", size: theFontSizeYouPrefer))