📕

BasicTextFieldを使って、TextFieldをカスタマイズする

2021/11/27に公開

BasicTextFieldを使って、TextFieldをカスタマイズする

前提

  • version
    • Kotlin 1.5.31
    • Jetpack Compose 1.0.5

概要

Jetpack Composeで文字の入力を行う場合、基本的にはTextFieldを使うことになると思います。
多機能で非常に使いやすいComposableですが、現状ではTextField内のPaddingを変更することができません。

そのため、TextFieldの機能を超えてカスタマイズしたい場合は、BasicTextFieldを使うことになるでしょう。実際にBasicTextFieldを使った一例をメモしておきます。

内容

Paddingを可変とする方法

decorationBoxというコールバックの引数が存在します。
そしてdecorationBoxのコールバックの引数にはinnerTextFieldが渡ってくるため、
innerTextFieldをラップすることでPaddingをつけることができます。

      BasicTextField(
            value = "",
            onValueChange = {},
            decorationBox = { innerTextField ->
                Box(Modifier.padding(10.dp)) {
                    innerTextField()
                }
            }
        )

PlaceHolderをつけて、LeadingにIconを配置する

こちらもdecorationBox内で、任意のComposableを用いることで実現できます。

今回はLeading側にIconが欲しいため、Rowで配置します。
PlaceHolderはMutableStateの状態を確認し判断した上で、出し分けるようにすることでPlaceHolderが表示できます。

@Composable
fun LeadingIconTextFieldWithPlaceHolder() {
    val text = remember {
        mutableStateOf("")
    }
    BasicTextField(
        value = text.value,
        onValueChange = {
            text.value = it
        },
        decorationBox = { innerTextField ->
            Row {
                Icon(painterResource(id = R.drawable.ic_home), contentDescription = "home")
                if (text.value.isEmpty()) {
                    Text(text = "PlaceHolder")
                } else {
                    innerTextField()
                }
            }
        }
    )
}

まとめ

今回、メモした内容は簡易的な一例ですが、手軽にCustomizeできて非常に良いですね。
ただ、BasicTextFieldはTextFieldよりも低レイヤーなComponentであるため、ある程度自身で振る舞いを決める必要がありそうです。

デザインなどMaterialDesignなどに準拠したもので良い場合はTextfieldを使用し、
挙動やデザインを変更したい場合は、BasicTextfieldを使うのが良いかなと思いました。

また、複雑なレイアウトなどしたい場合は、TextFieldの実装を見にいくと参考になりそうです。

参考

https://github.com/androidx/androidx/blob/androidx-main/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BasicTextFieldSamples.kt

Discussion