🍇

SwiftUI の Text で複数行に渡る表示をいい感じにする(改行位置を整える)

2022/01/16に公開

Summary

  • 単語の途中で改行されることが少なくなって、とても読みやすい!
  • iOS 13.0 以降、 macOS 10.15 以降、tvOS 13.0 以降、watchOS 6.0 以降 で使える!

日本語文章の改行位置を整えてくれる Google の BudouX

画面やウィンドウの幅によってテキストが自動で改行されることがありますが、単語や文節の間にスペースが入らない日本語の場合、改行位置が微妙になってしまうことがあります。

https://twitter.com/hima_papa0831/status/1474679838942568450?s=20

これをよろしく解決してくれる Python、JavaScript 向けライブラリが google/budoux です。

https://github.com/google/budoux

また、これを Swift でも使えるようにされたのが griffin-stewie/BudouX.swift です。

https://github.com/griffin-stewie/BudouX.swift

そして今回、griffin-stewie/BudouX.swift v0.4.0 がリリースされ、SwiftUI でも簡単に扱えるようになったので紹介します。

https://github.com/griffin-stewie/BudouX.swift/releases/tag/v0.4.0

TextBudouXText に置き換えるだけ

iOS 13.0 以降、 macOS 10.15 以降、tvOS 13.0 以降、watchOS 6.0 以降で利用することができます(つまり SwiftUI の Text が使える環境であれば OK です)。

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。")
            .multilineTextAlignment(.center)
    }
}

上記のように SwiftUI の Text とある部分を BudouXText に置き換えてみましょう。

import SwiftUI
import BudouX

struct ContentView: View {
    var body: some View {
        BudouXText("あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。")
            .multilineTextAlignment(.center)
    }
}

SwiftUI の TextBudouXText の両方を表示させたプレビューがこちらです。

.multilineTextAlignment(.center) が指定されているので、BudouX のちからがより発揮されていますね!とても読みやすいです。

BudouXText の実装

BudouXText の実装は Sources/BudouX/SwiftUI/BudouXText.swift にあります。

// griffin-stewie/BudouX.swift v0.5.0

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func BudouXText(_ key: String, tableName: String? = nil, bundle: Bundle? = nil, comment: StaticString? = nil, parser: BudouX.Parser = .init(), threshold: Int = BudouX.Parser.defaultThreshold, condition: (_ naturalLanguagesSupportedByParser: Set<String>) -> Bool = defaultBudouXTextCondition) -> SwiftUI.Text

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public func BudouXText(verbatim content: String, parser: BudouX.Parser = .init(), threshold: Int = BudouX.Parser.defaultThreshold, condition: (_ naturalLanguagesSupportedByParser: Set<String>) -> Bool = defaultBudouXTextCondition) -> SwiftUI.Text

lower-camel-case ではありませんが、BudouX を import すると使えるグローバルなメソッドになっており、これは SwiftUI の Text を返すようになっています。[1]また、ローカライズにも対応しています。

メソッドの最後尾引数である condition で、BudouX のパーサーがサポートしている自然言語の Set が得られるので、例えば日本語のテキストの場合は true、そうでない場合は false を返すようにすると、日本語のときだけ BudouX による変換を行うように変更することもできます。

SwiftUI の Text で使える View Modifier もすべて利用可能

先述のような実装のため、BudouXText では SwiftUI の Text で使える View Modifier がすべて利用できます。そのため、日本語の文章で改行が気になるところがあれば、何も考えずに BudouXText に置き換えることが可能です。[2]

参考

https://zenn.dev/griffin_stewie/articles/2112211657_introducing_budoux_swift

脚注
  1. なぜメソッドなのに命名が lower-camel-case ではないかについては、Pull request に説明があります。 ↩︎

  2. budouxed(_:) のような SwiftUI の Text で使える View Modifier の方がよかったのでは…?と思ったりしますが、なぜそうならなかったかについては Pull request に説明があります。 ↩︎

Discussion