はじめに

今回はJetpackCompose、material3のコンポーネントのひとつ、androidx.compose.material3.OutLineTextField(以下OutLineTextField)についての小ネタです。

要約すると以下の通りです。
早く解決したい!という方は後半のコードを参照してください。

  • OutLineTextFieldに設定されているpaddingは変更できないので一定未満の高さを設定すると文字が見切れる
  • 縦幅の狭いOutLineTextFieldは現状カスタムするしかなさそうなのでBasicTextFieldをベースに作りましょう

環境

  • Android Studio Iguana | 2023.2.1
  • androidx.compose.runtime:runtime:1.6.3
  • androidx.compose.ui:ui:1.6.3
  • androidx.compose.material3:material3:1.2.1

本文

例えば、検索関連やチャット入力、あるいはフォーム画面の入力欄として外枠つきの入力フィールドを使いたかったり、デザインで指定されたりということはよくあるかと思います。
そこで実装しようとしてまず出てくるのがOutLineTextFieldだと思います。
標準であるなら使いたいですね、使ってみましょう。

※一部省略しています

Row(verticalAlignment = Alignment.CenterVertically) {
    Text(text = "入力欄:Modifier指定なし")
    OutlinedTextField(
        modifier = Modifier.padding(start=8.dp),
        value = editText,
        onValueChange = { newValue ->
            editText = newValue
        }
    )
}

画像1

意外と大きいですよね。よく見る外枠つきの入力欄は(個人的には)もう少し小さい気がします。
なので高さを変えてみます。

※一部省略しています

Row(verticalAlignment = Alignment.CenterVertically) {
    Text(text = "入力欄:高さ40dp")
    OutlinedTextField(
        modifier = Modifier
            .height(40.dp) // ← ここを追加
            .padding(start = 8.dp),
        value = editText,
        onValueChange = { newValue ->
            editText = newValue
        }
    )
}

画像2

見切れました。前置きで書いた通り、標準で設定されているpaddingがあるためこのような表示になってしまいます。
このpaddingは指定できず、どこで設定しているかというとOutlinedTextField内、OutlinedTextFieldDefaults.DecorationBoxのcontentPadding標準値が使われております(上下左右:16dp)
(補足として以下にコードを貼りますが、AndroidStudio上で確認するのが早いと思います。)

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt;l=197-217

https://androidx.tech/artifacts/compose.material3/material3/1.1.2-source/androidx/compose/material3/TextFieldDefaults.kt.html

つまりはTextFieldのdecorationBoxにこちらでpaddingを指定したものを作れば良いというわけです。
だいたいこのような感じになります。実際に使う場合はコンポーネントの使用範囲に応じて適宜カスタマイズ性を持たせるのが良いかと思います。

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CustomOutLineInputBox(
    modifier: Modifier = Modifier,
    textStyle: TextStyle = LocalTextStyle.current,
    value: String,
    enabled: Boolean = true,
    onValueChange: (String) -> Unit
) {
    val singleLine = true
    val interactionSource = remember { MutableInteractionSource() }
    BasicTextField(
        value = value,
        onValueChange = onValueChange,
        modifier = modifier.fillMaxWidth(),
        singleLine = singleLine,
        textStyle = textStyle,
        interactionSource = interactionSource,
    ) { innerTextField ->
        OutlinedTextFieldDefaults.DecorationBox(
            value = value,
            innerTextField = innerTextField,
            enabled = enabled,
            singleLine = singleLine,
            visualTransformation = VisualTransformation.None,
            interactionSource = interactionSource,
            colors = OutlinedTextFieldDefaults.colors(),
            // ここの値を指定する //
            contentPadding = TextFieldDefaults.contentPaddingWithoutLabel(
                top = 0.dp,
                bottom = 0.dp,
            ),
        ) {
            OutlinedTextFieldDefaults.ContainerBox(
                enabled = enabled,
                isError = false,
                interactionSource = interactionSource,
                colors = OutlinedTextFieldDefaults.colors(),
                shape = RoundedCornerShape(4.dp),
                focusedBorderThickness = OutlinedTextFieldDefaults.FocusedBorderThickness,
                unfocusedBorderThickness = OutlinedTextFieldDefaults.UnfocusedBorderThickness,
            )
        }
    }
}

画像3

終わりに

余談ですがこれについては割と前にissueTrackerで取り上げられており、リクエストも上がっているのですが、正直内容が内容なので対応されるにしろ優先度は低いのかなと個人的には思います……。

今回の外枠に限らず、デザイン要望によりdecorationBoxをカスタマイズしたい!ってこともあるとは思うのでどちらにせよ覚えておいて損はないと思います。

https://issuetracker.google.com/issues/228928703 https://issuetracker.google.com/issues/321893748



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる