入力中のテキストフィールドのラベルをいい感じに浮かせたい【Jetpack Compose】

## 今回解決したいこと
#### テキストフィールドの入力中の値とラベルの間に隙間をあけたい。

入力前はいい感じに見えるけど、
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798901/6163c79d-6a19-4d19-8e4d-5b9acc040d52.png">

ラベルが上がったとき、入力中の文字との隙間が狭いのがちょっと気になるので、
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798901/a6d6dab2-1cc5-446d-ace1-b41f085c3caf.png">
↓
こうしたい！
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798901/883c3fc3-13b4-4973-9cdb-77a8f9328bb9.png">

## 実装方法
方法の概要としては、
- Compose に用意されている`TextField`の中身を拝借
- 入力エリアである`innerTextField`の周りを好きな`Padding`で囲む

以上です。実際のコードは以下の通りです。

```kotlin

// ⭐️composeで元々用意されているTextFieldのコード


@Composable
fun CustomTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    // 
    //（省略）
    //
) {
    @OptIn(ExperimentalMaterialApi::class)
    BasicTextField(
        value = value,
        //
        //（省略）
        //
        decorationBox = @Composable { innerTextField ->
            TextFieldDefaults.TextFieldDecorationBox(
                value = value,
                //
                //（省略）
                //
                // ↓ここ↓ innerTextFieldがそのまま渡されている
                innerTextField = innerTextField
            )
        },
    )
}
```

上記の`innerTextField`がそのまま渡されているところを、好きなPaddingで囲います。

```kotlin

// ⭐️好きなPaddingを足したコード


@Composable
fun CustomTextField(
    value: String,
    // 
    //（省略）
    //
) {
    @OptIn(ExperimentalMaterialApi::class)
    BasicTextField(
        value = value,
        // 
        //（省略）
        //
        decorationBox = @Composable { innerTextField ->
            TextFieldDefaults.TextFieldDecorationBox(
                value = value,
                // 
                //（省略）
                //
                // ↓ここ↓  paddingで囲み、任意の隙間を作る
                innerTextField = {
                    Box(Modifier.padding(top = 8.dp)) {
                        innerTextField()
                    }
                },
            )
        },
    )
}
```
さらに、`innerTextFieldPadding` といった引数を用意すれば、呼び出し側で好きなPaddingValuesを渡せるようになり、汎用性が高まります。

```kotlin

// ⭐️Paddingの値を外から渡せるようにしたコード


@Composable
fun CustomTextField(
    // 
    //（省略）
    //
    innerTextFieldPadding: PaddingValues = PaddingValues(0.dp),
) {
    @OptIn(ExperimentalMaterialApi::class)
    BasicTextField(
        // 
        //（省略）
        //
        decorationBox = @Composable { innerTextField ->
            TextFieldDefaults.TextFieldDecorationBox(
                // 
                //（省略）
                //
                // ↓ここ↓ 外から値を渡せるようにすると汎用性が高まる
                innerTextField = {
                    Box(Modifier.padding(innerTextFieldPadding)) {
                        innerTextField()
                    }
                },
            )
        },
    )
}
```


このカスタムTextFieldによって、シンプルなデザインもカッコよく作れるようになりました。

<img width=60% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798901/4fd16a93-62df-404f-b1fa-c3b8a0778a75.png">


# まとめ
innerTextField にパディングを与えることで、ラベルと入力値の間に任意の隙間をつくることができました。内部構造に手を加えることは、参考資料にもある通りリスクも伴いますが、見た目を丁寧に整えたい場面では有効な方法です。

最近ではMaterial3がどんどん洗練されていっており、キャッチアップの大切さを感じる日々ですが、Compose Multiplatformを採用しiOSの安定動作を目指す場合や、Material2を採用している場合は、こうした工夫がまだまだ活きると感じています。見た目や体験にこだわりたいときに、ぜひ試してみてください。


### ⭐️ 参考資料
https://qiita.com/kdrn/items/b30678bec92297616843