6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TextFieldを小さくしたいだけなのに

Posted at

困ったこと

「TextFieldの高さを小さくしたい・・・」

TextFieldの高さを小さくしたい場合、デフォルトの設定では難しいことがあります。
本記事では、その解決方法について説明します。

TextFieldの高さ

まず、以下のようにTextFieldを作成してみます。

var text by remember { mutableStateOf("") }
 
TextField(
    value = text,
    onValueChange = { text = it },
    placeholder = { Text(text = "入力してください", color = Color.Gray) },
    modifier = Modifier.fillMaxWidth()
)

qiita.001.jpeg

特にpaddingなどを指定していないにもかかわらず、内部には適度な隙間が生じます。これは、TextFieldにデフォルトで16.dpのpaddingが設定されているためです。

では、デフォルトのTextFieldよりも高さが小さいTextFieldを実現するにはどうすれば良いのでしょうか?(^_^;)

🙅‍♀️TextFieldにheightを指定する

以下のようにheightを直接指定してみます。

TextField(
    value = text,
    onValueChange = { text = it },
    placeholder = { Text(text = "入力してください", color = Color.Gray) },
    modifier = Modifier.fillMaxWidth()
                       .height(45.dp)  // heightを追加
)

qiita.002.jpeg

フォーム内部の要素が潰れてしまいました。そんな・・・
ちなみに親要素にheightを指定しても同じことが起きます。

Paddingの指定を外側から書き換えにいく

問題の原因となるpaddingを特定し、これを調整する方法を考えます。

TextFieldの内部

TextFieldの内部では、BasicTextFieldが呼び出され、さらにそのdecorationBoxTextFieldDefaults.TextFieldDecorationBoxが利用されています。

@Composable
fun TextField(
    value: String,
    onValueChange: (String) -> Unit,
    // 
    //(省略)
    //
    )

    @OptIn(ExperimentalMaterialApi::class)
    BasicTextField(
        value = value,
        //
        //(省略)
        //
        decorationBox = @Composable { innerTextField ->
            // places leading icon, text field with label and placeholder, trailing icon
            TextFieldDefaults.TextFieldDecorationBox(
                value = value,
                //
                //(省略)
                //                    
            )
        }
    )
}

TextFieldDefaults.TextFieldDecorationBoxの内部

TextFieldDefaults.TextFieldDecorationBoxでは、以下のようにcontentPaddingが設定されています。

@Composable
    @ExperimentalMaterialApi
    fun TextFieldDecorationBox(
        //
        //(省略)
        //

        // ↓↓↓ 注目‼️ ↓↓↓
        contentPadding: PaddingValues =
            if (label == null) {
                textFieldWithoutLabelPadding()
            } else {
                textFieldWithLabelPadding()
            }
        ) {
        CommonDecorationBox(
            //
            //(省略)
            //
            contentPadding = contentPadding
        )
    }

ここで16.dpが指定されていました。このcontentPaddingを外部から変更可能な形でカスタマイズします。

CustomTextField(自前実装)

以下にカスタマイズ可能なCustomTextFieldを実装します。

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CustomTextField(
    value: String,
    onValueChange: (String) -> Unit,
    placeholder: @Composable (() -> Unit)? = null,
    modifier: Modifier,
) {
    BasicTextField(
        modifier = modifier,
        value = value,
        onValueChange = onValueChange,
        decorationBox = @Composable { innerTextField ->
            androidx.compose.material3.TextFieldDefaults.DecorationBox(
                value = value,
                visualTransformation = VisualTransformation.None,
                innerTextField = innerTextField,
                placeholder = placeholder,
                enabled = true,
                singleLine = true,
                interactionSource = remember { MutableInteractionSource() },
                // ↓↓↓ ここで上書きする‼️ ↓↓↓
                contentPadding = PaddingValues(0.dp),
            )
        }
    )
}

使用例:

CustomTextField(
    value = text,
    onValueChange = { text = it },
    placeholder = { Text(text = "入力してください", color = Color.Gray) },
    modifier = Modifier.fillMaxWidth()
)

qiita.003.jpeg

これで、TextFieldの高さを小さくすることができました!

おわりに

以上のように、contentPadding部分を上書きすることで、TextFieldの高さを小さくすることが可能です。ただしデフォルトの設定を上書きする方法にはリスクもあります。
将来、アップデートで挙動が変わる可能性もあるため注意が必要です。

より良い実装方法をご存じの方がいれば、ぜひ教えてください。

参考

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?