📝

[JetpackCompose] TextFieldについて色々

3 min read

ソースコード

@Composable
fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle = LocalTextStyle.current,
    label: () -> Unit = null,
    placeholder: () -> Unit = null,
    leadingIcon: () -> Unit = null,
    trailingIcon: () -> Unit = null,
    isError: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions(),
    singleLine: Boolean = false,
    maxLines: Int = Int.MAX_VALUE,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape = MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()
): @Composable Unit

引数はこの様になっており、色々とカスタムできる様になっている。

例えば中央表示にしたい場合は、

textStyle: にTextAlign.Centerにで中央表示することができる。

状態の変更

composeは基本的に状態を持っていないので、

Valueに変更を通知して状態を変えてあげないと、

状態が追えないのでTextFieldがずっと空白のままになる。

mutableStateで変更可能な状態を作り、

後はなんかややこしいことしなければならない雰囲気である。

状態ホイスティングを使う

流石JetpackComposeというところで、

実はめちゃくちゃ簡単に変更を通知できる。

それが状態ホイスティングである。

var name by rememberSaveable { mutableStateOf("") }

で作ったnameをvalue:に入れ、

onValueChange:に{ name = it }を渡してあげると勝手にやってくれる。

すごく便利。

@Composable
fun HelloScreen() {
    var name by rememberSaveable { mutableStateOf("") }

    HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}

こんな感じ。

現状maxLengthがない(まじで????)

まじです。

忘れてね???大丈夫????って感じなのですが、

ないものはしょうがないので何かしら対応をしなければなりません.......

maxLengthの打開策

@Composable
fun PinCodeField() {
    var text by remember { mutableStateOf("") }
    OutlinedTextField(
        value = text,
        onValueChange = { text = maxLength(it, 1) }
    )
}

private fun maxLength(input: String, maxLength: Int) = if (input.length > 1) input.substring(0,maxLength) else input

inputに対してsubstringで制御するという形を現状取っています。

onValueChange に作った関数maxLength(it, 制御したい数)という形。

参考記事

https://developer.android.com/jetpack/compose/text?hl=ja

https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#TextField(kotlin.String,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.Boolean,androidx.compose.ui.text.TextStyle,kotlin.Function0,kotlin.Function0,kotlin.Function0,kotlin.Function0,kotlin.Boolean,androidx.compose.ui.text.input.VisualTransformation,androidx.compose.foundation.text.KeyboardOptions,androidx.compose.foundation.text.KeyboardActions,kotlin.Boolean,kotlin.Int,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.ui.graphics.Shape,androidx.compose.material.TextFieldColors)

https://developer.android.com/jetpack/compose/state?hl=ja#state-hoisting「

http://y-anz-m.blogspot.com/2021/04/jetpack-compose-basictextfield.html

http://www.chansek.com/maxLength-alternative-jetpack-compose/

デザイン参考

https://pratikchauhan11.medium.com/playing-with-textfield-in-compose-android-declarative-ui-de8c03aa4748

Discussion

ログインするとコメントできます