Android / Kotlin / Programming

TextFieldの下線の幅(長さ)を変更したい

Android Jetpack Composeでテキスト入力を受け付けるコンポーネントであるTextFieldの入力フィールドの下についている線の距離を縮める方法を載せています

※下記ではTextFieldDefaults.DecorationBoxと書いていますが、Androidの公式リファレンスにはTextFieldDefaults.TextFieldDecorationBoxと記載があります
恐らく私の使っているバージョンが古いためだと思われますが、適宜読み替えてください

まず、初期状態の動きを確認します

var textFieldValue by rememberSaveable { mutableStateOf("") }
TextField(
    value = textFieldValue,
    onValueChange = {
        textFieldValue = it
    },
    modifier = Modifier
        .wrapContentSize()
        .defaultMinSize(
            minWidth = TextFieldDefaults.MinWidth,
            minHeight = TextFieldDefaults.MinHeight
        ),
    textStyle = Typography.bodyMedium,
    label = {
        Text(
            text = "グループ名",
            style = Typography.labelSmall
        )
    },
    placeholder = {
        Text(
            text = "グループ名を入力",
            style = Typography.bodyMedium
        )
    }
)

赤い部分を不要個所として取り除くのが今回の目的になります

Code

いきなりですがコードと実際のキャプチャはこちらです

var textFieldValue by rememberSaveable { mutableStateOf("") }
val interactionSource = remember { MutableInteractionSource() }
BasicTextField(
    value = textFieldValue,
    onValueChange = {
        textFieldValue = it
    },
    modifier = Modifier
        .wrapContentSize()
        .defaultMinSize(
            minWidth = TextFieldDefaults.MinWidth,
            minHeight = TextFieldDefaults.MinHeight
        ),
    textStyle = Typography.bodyMedium,
    interactionSource = interactionSource,
    decorationBox = @Composable { innerTextField ->
        TextFieldDefaults.DecorationBox(
            value = textFieldValue,
            innerTextField = innerTextField,
            enabled = true,
            singleLine = true,
            visualTransformation = VisualTransformation.None,
            interactionSource = interactionSource,
            isError = false,
            label = {
                Text(
                    text = labelText,
                    style = Typography.labelSmall
                )
            },
            placeholder = {
                Text(
                    text = placeHolderText,
                    style = Typography.bodyMedium
                )
            },
            contentPadding = PaddingValues(
                end = 16.dp
            )
        )
    }
)

詳細

BasicTextFieldの使用

下線の長さの変更をTextFieldに指定する引数で変更できれば一番良いのですが、現在(2024/7/20)では不可能です
Material3Androidリファレンスを参照しても載っていません
しかしBasicTextFieldを使用すれば可能になります

BasicTextFieldとはTextFieldが内部で使用しているTextFieldの基礎となる関数です
AndroidCodeSearchで見てみると使用されていることがわかると思います
このBasicTextFieldで指定できる「decorationBox」パラメーターが今回の肝となります

decorationBoxパラメーターとは、こちらを参考にすると、「アイコン・プレースホルダー・説明用のメッセージなどテキスト入力欄の周りに変更を加えるためのコンポーザブルなラムダ」となっています
TextFieldからBasicTextFieldを呼び出すときも、受け取ったラベルやプレースホルダーなどはdecorationBoxパラメーターに指定している関数に渡しています

TextFieldDefaults.DecorationBoxの使用

BasicTextFieldのdecorationBoxパラメーターにはコンポーザブルなラムダを指定できますが、指定におすすめの関数があります
それがTextFieldDefaults.DecorationBoxです

TextFieldDefaults.DecorationBoxは、TextFieldでも使用されている入力欄をベースに、カスタマイズした入力欄を作成できる関数です
実際にTextFieldでも内部でTextFieldDefaults.DecorationBoxを使用しており、関数の説明欄にも「TextFieldのパラメーターで変更不可能な要素のカスタマイズが必要な場合は、TextFieldDefaults.DecorationBoxを使用し要望を満たせるかを検討してください」と記載があります

こちらのTextFieldDefaults.DecorationBoxが提供しているcontentPaddingパラメーターにstartのpaddingを抜いた状態のPaddingValuesクラスを渡せば問題解決です

おわりに

今回紹介したBasicTextFieldはExperimentalMaterial3Apiアノテーションが付与されているため、将来的な変更や削除などの可能性があります
しかしTextFieldでも内部でこちらを使用しているため使用自体に問題は一切ないと考えられます
ただ変更があった際にBasicTextFieldを使用しているコンポーネントも変更が必要になるため注意が必要です

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です