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

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

:::note info
TextFieldDefaults.DecorationBoxと下記に記載がありますが、Androidの公式リファレンスにはTextFieldDefaults.TextFieldDecorationBoxと紹介されています。
恐らく私の使っているバージョンが古いためだと思われますが、適宜読み替えてください。
:::
まず、初期状態の動きを確認します。
# 通常
```kotlin
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
        )
    }
)
```
<img src="https://vegcale.com/home/wp-content/uploads/2024/07/textfield-with-extra-padding.webp"/>

こちらの赤い部分のように、前方のスペースと下線が表示されます。これを取り除くのが今回の目的です。
# 対応済みコード
```kotlin
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
            )
        )
    }
)
```
<img src="https://vegcale.com/home/wp-content/uploads/2024/07/image-1.webp"/>

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

BasicTextFieldとはTextFieldが内部で使用しているTextFieldの基礎となる関数です。[AndroidCodeSearch](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt;l=394?q=file:androidx%2Fcompose%2Fmaterial3%2FTextField.kt%20function:TextField)で見てみると使用されていることがわかると思います。このBasicTextFieldで指定できる「decorationBox」パラメーターが今回の肝となります。

decorationBoxパラメーターとは、[こちら](https://androidx.tech/artifacts/compose.foundation/foundation/1.0.0-alpha08-source/androidx/compose/foundation/text/BasicTextField.kt.html)を参考にすると、「アイコン・プレースホルダー・説明用のメッセージなどテキスト入力欄の周りに変更を加えるためのコンポーザブルなラムダ」となっています。TextFieldからBasicTextFieldを呼び出すときも、受け取ったラベルやプレースホルダーなどはdecorationBoxパラメーターに指定している関数に渡しています。
## TextFieldDefaults.DecorationBoxの使用
BasicTextFieldのdecorationBoxパラメーターにはコンポーザブルなラムダを指定できますが、指定におすすめの関数があります。それが[TextFieldDefaults.DecorationBox](https://developer.android.com/reference/kotlin/androidx/compose/material/TextFieldDefaults#TextFieldDecorationBox(kotlin.String,kotlin.Function0,kotlin.Boolean,kotlin.Boolean,androidx.compose.ui.text.input.VisualTransformation,androidx.compose.foundation.interaction.InteractionSource,kotlin.Boolean,kotlin.Function0,kotlin.Function0,kotlin.Function0,kotlin.Function0,androidx.compose.ui.graphics.Shape,androidx.compose.material.TextFieldColors,androidx.compose.foundation.layout.PaddingValues))です。

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

こちらのTextFieldDefaults.DecorationBoxが提供しているcontentPaddingパラメーターにstartのpaddingを抜いた状態のPaddingValuesクラスを渡せば問題解決です。
# おわりに
今回紹介したBasicTextFieldはExperimentalMaterial3Apiアノテーションが付与されているため、将来的な変更や削除などの可能性があります。しかしTextFieldでも内部でこちらを使用しているため使用自体に問題は一切ないと考えられます。ただ変更があった際にBasicTextFieldを使用しているコンポーネントも変更が必要になるため注意が必要です。

最後まで読んでいただきありがとうございます！質問やご指摘等ありましたらお気軽にご連絡ください！
「いいね」やフォローもお願いします！！

個人ブログではQiitaに載せきれていない内容もあるので、ご興味ありましたら是非みてください！！！

https://vegcale.com/