こんにちは!Jetpack Compose と KMM が好きなエンジニアのスージです。
Jetpack Compose v1.3.0 から改行方法を指定できる新しいAPI @ExperimentalTextApi LineBreak
が追加されています。この記事では LineBreak
に渡すパラメータによって改行方法がどのように異なるのかについて調べてみました。
android-developers.googleblog.com
文章によって結果が変わるので、あくまで一例としてご覧ください。🙇♂️
LineBreak
v1.3.0 からTextStyle
では lineBreak
のパラメータが追加されました。
/** * .. * @param lineBreak The line breaking configuration for the text. */ @Immutable class TextStyle internal constructor( .. lineBreak: LineBreak? = null, )
このLineBreak
クラスに3つのパラメータを渡します。
/** * .. * @param strategy defines the algorithm that inserts line breaks * @param strictness defines the line breaking rules * @param wordBreak defines how words are broken */ @ExperimentalTextApi @Immutable actual class LineBreak( val strategy: Strategy, val strictness: Strictness, val wordBreak: WordBreak )
Strategy
LineBreak.Strategy
は改行する方針を決めるパラメータです。3つのタイプがあります。
- Simple:処理が一番早い方針です。
- Balanced:ハイフンを含めて、文章の各行の長さをなるべくバランス良くする方針です。
- HighQuality:言葉自体をなるべく改行しない方針です。
Strategy.Balanced
の場合言葉を改行しても、ずっと各行の長さが同じで綺麗に見えますね。
同じく v1.3.0
で追加されたHyphenation APIを有効にすれば、ハイフンを含めて改行の調整を行います。英語みたいなハイフンで言葉を改行できる言語しか影響しないです。
Strictness
LineBreak.Strictness
は改行のアルゴリズムを決めるパラメータです。 Loose
、Normal
とStrict
ではそれぞれの名前通りの厳密性で、どの文字のあと改行できるかを決定します。ドキュメンテーションでも書いてありますが、CJKフォントに影響がありそうです。
- Loose : 例えば、「々」の前にも改行します。一番低い厳密性で改行してしまうのでタイトルみたい短いテキストに使うのがおすすめです。
- Normal:日本語の場合「ぁ」「ィ」の前にも改行する。
- Strict:日本語の場合「々」と「ぁ」「ィ」の前に改行しない。一番高い厳密性なので処理もより重くなります。
英語の場合は Strictness
は影響しなさそうですね。
WordBreak
LineBreak.WordBreak
は単語を改行する方針を決めるパラメータです。2つのタイプがあります。
- Default:言語のデフォルトの単語の改行方法です。日本語みたいな単語の間にスペースがない言語では言葉の中でも改行を入れます。
- Phrase:なるべくフレーズを改行させないようにします。
途中で「色々美味しいもの食べましょう」はWordBreak.Default
の場合「色々美味しいもの食べ」「ましょう」に改行されてますが、WordBreak.Phrase
の場合は「美味しいもの」「食べましょう」に改行されてますね。
良い事例思いつかなかったのですが、英語の場合 Default と Phrase は同じでした。
プリセット
LineBreak
APIでアプリでよく使う3タイプのユースケースのプリセットも用意されてます。
LineBreak.Simple
高頻度で更新されるテキスト(TextField
など)のための、一番早いアルゴリズムで処理させる用の LineBreak
です。
/** * The greedy, fast line breaking algorithm. Ideal for text that updates often, * such as a text editor, as the text will reflow minimally. .. */ actual val Simple: LineBreak = LineBreak( strategy = Strategy.Simple, strictness = Strictness.Normal, wordBreak = WordBreak.Default )
Strategy.Simple
:処理スピードが一番早いStrictness.Normal
:可読性を守りつつ処理が一番早いWordBreak.Default
:言語デフォルト
LineBreak.Heading
あまり改行しないテキスト(タイトルなど)のための LineBreak
です。
/** * Balanced line lengths, hyphenation, and phrase-based breaking. * Suitable for short text such as titles or narrow newspaper columns. .. */ actual val Heading: LineBreak = LineBreak( strategy = Strategy.Balanced, strictness = Strictness.Loose, wordBreak = WordBreak.Phrase )
Strategy.Balanced
:長さを同じようにして綺麗に見せるStrictness.Loose
:一番低い厳密性WordBreak.Phrase
:フレーズ毎改行する方針
LineBreak.Paragraph
処理時間もかかり、可読性が優先される文章(説明、長文など)のための LineBreak
です。
/** * Slower, higher quality line breaking for improved readability. * Suitable for larger amounts of text. .. */ actual val Paragraph: LineBreak = LineBreak( strategy = Strategy.HighQuality, strictness = Strictness.Strict, wordBreak = WordBreak.Default )
Strictness.Strict
:高い厳密性Strategy.HighQuality
:言葉自体をなるべく改行しない方針
日本語の場合は単語間にスペースがないので、WordBreak.Default
より WordBreak.Phrase
を使った方が良いかもしれないです。なので、日本語の場合はWordBreak.Phrase
を使った方がいいと思いました。
lineBreak = LineBreak.Paragraph.copy(wordBreak = WordBreak.Phrase)
おわりに
今回調べてみた LineBreak
API は元々View.java
時代から存在してるものなのですが、Compose の読みやすさと早く検討できるおかげでより良い理解ができたかなと思いました。