X

Jetpack Compose: Textコンポーザブルを使う

技術書典11で出版予定のJetpack Compose特集にあわせて、しばらくJetpack Composeをブログ上でも紹介したいと思います。筆者も学びながらメモしているので、こんな情報もあるよ!ここのブログ良かったよなどあれば随時教えて下さい。

今回はJetpack Composeのサンプルとして一番最初に触れることになるTextコンポーザブル( androidx.compose.material.Text )です。テキストの表示を担当していて、複数の異なるスタイルをテキストに反映させたり、テーマなどのスタイル情報を利用したりできる高レベルのテキスト要素コンポーザブルです。

余談ですがandroidx.compose.material.Textの内部ではandroidx.compose.foundation.textのBasicTextやCoreTextを呼び出しています。低レベルのテキスト要素を扱うCoreText、BasicTextを使いやすくWrapしたコンポーザブルと言い換えてもよいでしょう。

テキストを表示する

TextコンポーザブルのPreview表示

最も単純に、静的なテキストを表示したい場合、TextコンポーザブルにString型のtextを引数で渡すだけです。

@Composable
fun TextSample() {
    Text(text = "This is a sample text")
}

可変テキストを表示する

一部を変数として扱いたい場合はtext引数を次のとおり、変数を含むものに差し替えてください。

@Composable
fun SimpleText(name: String) {
    Text(text = "Hello $name!")
}

リソースから取得したテキストを表示する

文字列リソースを表示したい場合、つまりこちらが多くのアプリケーションでありえるユースケースです。text引数をハードコードしてしまうと多言語対応ができないのでstringResourceコンポーザブルを使って表示するテキストを取得します。

@Composable
fun StringResourceText() {
    //Contextからリソースを取得している
    Text(stringResource(R.string.app_name))
}

stringResourceコンポーザブルはリソースへの参照を保持しているユーテリティです。サンプルではアプリケーション名の文字列リソース(R.string.app_name)を取り出して表示しています。

Contextやリソースへのアクセス

Android Viewシステムを知っている人にとっては、stringResourceコンポーザブルで「Contextへアクセスしているのでは?」と気づいたかもしれません。これは stringResourceコンポーザブル内部で暗黙的にContextとResourcesを探しgetStringメソッドで取得して実現しています。

Jetpack Composeでは従来のViewシステムで必須であったConfigurationやContextをLocalConfiguration、LocalContextという形で提供しています。これらはComposeを実現しているランタイム部分で管理されており、androidx.compose.ui.platformではそれ以外にもLocalLifecycleOwnerなどその他のAndroidプラットフォームへの依存を制御しています。Textコンポーザブルの話題からは逸れてしまいましたが既存のViewシステムから逸脱しないでComposeのメリットを享受できる工夫がみてとれます。

テキストのスタイルを変更する

テキストを装飾する

Textコンポーザブルの引数でテキストを装飾できます。次のサンプルはフォントカラー、フォントサイズ、斜体への変更、ウェイトをボールドへ、フォントファミリーの変更、中央寄せの一例です。

@Preview(showBackground = true)
@Composable
fun StyledText() {
    Column() {
        Text(text = "This is a sample text", color = Color.Red)
        Text("FontSize is 24sp", fontSize = 24.sp)
        Text("Italic", fontStyle = FontStyle.Italic)
        Text("Bold", fontWeight = FontWeight.Bold)
        Text("SansSerif", fontFamily = FontFamily.SansSerif)
        Text(
            "TextAlign.Center", textAlign = TextAlign.Center,
            modifier = Modifier.width(150.dp)
        )
    }
}

それぞれ必要な引数のみ指定しています。最後の中央揃えはTextAlign.Centerで実現していますが言語によっては左始まり、右始まりが異なります。左右への指定ではなく始まり・終わりを意味するTextAlign.Start や TextAlign.Endを使うようにしましょう。

今回のサンプルにおけるTextAlign.Centerの解釈

今回、テキストの中央寄せはTextコンポーザブルの横幅を150dpと指定することで実現しています。親要素となるColumnコンポーザブルの横幅と一致していないため「見た目が中央寄せになってないな?」と感じるかもしれません(が、コードは指定されたとおりちゃんとTextAlignを「中央寄せ」しているんですよ)。

もし前述の挙動に不満がある場合、求めているものはTextAlignではなくレイアウトの中央寄せかもしれません。親要素の横幅に合わせて中央寄せを行う場合、次のようにも書けます。

親要素のBoxコンポーザブルの横幅に合わせてセンタリングする
@Preview(showBackground = true)
@Composable
fun BoxExample() {
    Box(Modifier.width(200.dp)) {
        Text("This text is Alignment.Center", 
            modifier = Modifier.align(Alignment.Center))
    }
}

Textコンポーザブルの引数のmodifierへModifier.align(Alignment.Center)を与えています。この指定であればサンプルの場合、親要素のレイアウトに合わせて中央に表示できています。

親要素に対するレイアウト指定

ModifierやTextなどJetpack Compose以外でもよく使われるクラス名は
意図せず 誤ったimportをしてしまうことがあります。たとえばandroidx.compose.ui.Modifierではなく、java.lang.reflect.Modifierなど別のものと取り違えるなどです。自動補完すると起きやすいため気をつけましょう(あるはずのメソッドが見つからないエラーがでたときなどに思い出してください)。

Textコンポーザブルの引数

@Composable
fun Text(
    text: AnnotatedString,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
) {
  • text:表示する文字列
  • modifier:レイアウトへ反映するmodifier
  • color:フォントカラー(未指定ではLocalContentColorを利用)
  • fontSize:グリフのサイズを指定
  • fontStyle:斜体または通常。書体の指定
  • fontWeight:フォントの太さを指定(Boldなど)
  • fontFamily:同じコンセプトで作られた書体のグループ
  • letterSpacing:文字間の挿入するスペース幅
  • textDecoration:文字への装飾追加(アンダーライン等)
  • textAlign:テキストの寄せ方向(中央、開始、終了)
  • lineHeight:テキストボックスの高さを指定する
  • overflow:文字列が溢れた際の処理方法。Clip(切り捨て)、Ellipsis(省略)、Visible(表示)
  • softWrap:行の折り返し許可
  • maxLines:テキスト表示の最大行数
  • onTextLayout:テキストレイアウトが計算されたときに実行するコールバック指定
  • style:スタイルの指定(未指定の場合、LocalTextStyleを利用)

今回は、Textコンポーザブルの基本を紹介しました。次のリファレンスはより深い理解に役に立つはずです。次にTextコンポーザブルを扱うときは複数のテキストスタイルを混ぜて利用する方法、ユーザー操作、テキストの入力と変更に触れてみたいと考えています。

今回の記事はこれでおしまいです。お疲れさまでした。

mhidaka: Software Engineerだよ。DroidKaigi Organizer / Androidと組込とRe:VIEW。techbooster主宰。mhidaka's writings http://booklog.jp/users/mhidaka 技術書典! http://techbookfest.org