🍇

【SwiftUI】英語フォントと日本語フォントを併用する

に公開

概要

  • SwiftUIにおいて、英語フォントと日本語フォントを併用する方法を考えてみる

想定するケース

  • ヒラギノ角ゴシックで構成される日本語テキストとFuturaで構成される英語テキストの2種類から構成される文字列に、それぞれ異なるフォントを適用する。
  • 使用するフォントはそれぞれ、ヒラギノ角ゴシックFuturaの2種類とする。

実装案 1)フォント指定を併用する

1-1. フォント指定の併用

  • 英語フォントが日本語に対応しないことを利用して、英語→日本語の順番で.fontモディファイアを2個連続で指定する。
  • まず英語にフォントを指定して、その後日本語にフォントを適用する。
  • 2個目の.fontが全体に対してフォント情報をオーバーライドしていなければ問題なく行けるはず

1-2. 実装

Text("USBメモリ")
    .font(.custom("Futura", size: 20))
Text("Wi-Fiスポット")
    .font(.custom("HiraginoSans-W6", size: 20))
Text("COVID検査")
    .font(.custom("Futura", size: 20))
    .font(.custom("HiraginoSans-W6", size: 20))

1-3.結果

  • 仮説通り、全てヒラギノ角ゴになってしまった。

Simulator Screenshot - iPhone 17 Pro - 2025-10-26 at 11.09.57.png

<hr>

実装案 2)カスタムModifierを使用する

2-1. カスタムModifierを使う

  • Textを分割して日本語と英語に区別する
  • それをHStackでくっつければそれっぽくなるのでは。

2-2. 実装

/// 英語or数字か判定する
extension String {
    var isAlphanumeric: Bool {
        let range = "[a-zA-Z0-9]+"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }
}

/// Modifierの定義
struct CustomText: ViewModifier {
    let contentText: String
 
    func body(content: Content) -> some View {
        let array_text = Array(contentText).map{String($0)}
        
        return HStack(spacing: 0) {
            ForEach(array_text, id: \.self) { item in
                if item.isAlphanumeric == true {
                    Text(item)
                        .font(.custom("Futura", size: 20))
                } else {
                    Text(item)
                        .font(.custom("HiraginoSans-W6", size: 20))
                }
            }
        }
    }
}

/// Viewを拡張して扱いやすくする
extension View {
    func customText(_ text: String) -> some View {
        self.modifier(CustomText(contentText: text))
    }
}

/// Viewを定義する
Text("").modifier(CustomText(contentText: "COVID検査"))

2-3.結果

  • 上手く実装できた。

Simulator Screenshot - iPhone 17 Pro - 2025-10-26 at 11.33.10.png

注意

謝辞

  • isAlphaNumericのコードは下記からお借りしました。

https://ios-docs.dev/string-character-type-extension/

Discussion