困ったこと
「TextFieldの高さを小さくしたい・・・」
TextFieldの高さを小さくしたい場合、デフォルトの設定では難しいことがあります。
本記事では、その解決方法について説明します。
TextFieldの高さ
まず、以下のようにTextFieldを作成してみます。
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it },
placeholder = { Text(text = "入力してください", color = Color.Gray) },
modifier = Modifier.fillMaxWidth()
)
特に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を追加
)
フォーム内部の要素が潰れてしまいました。そんな・・・
ちなみに親要素にheight
を指定しても同じことが起きます。
Paddingの指定を外側から書き換えにいく
問題の原因となるpadding
を特定し、これを調整する方法を考えます。
TextFieldの内部
TextFieldの内部では、BasicTextField
が呼び出され、さらにそのdecorationBox
に TextFieldDefaults.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()
)
これで、TextFieldの高さを小さくすることができました!
おわりに
以上のように、contentPadding
部分を上書きすることで、TextFieldの高さを小さくすることが可能です。ただしデフォルトの設定を上書きする方法にはリスクもあります。
将来、アップデートで挙動が変わる可能性もあるため注意が必要です。
より良い実装方法をご存じの方がいれば、ぜひ教えてください。
参考