Jetpack ComposeでButtonの自動パディングを消す方法
原因としては、3つ考えられます。
- ContentPadding を指定していない
- Buttonのサイズが48dp未満
- Buttonの中にあるコンポーザブルが58dp未満
ContentPaddingを指定していない
問題のあるコード
SampleView.kt@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier,
onClick = { /*TODO*/ },
) {
Box(Modifier.size(60.dp), contentAlignment = Alignment.Center) {
Text(
text = "サンプルボタン"
)
}
}
}
}
原因と解決策
ここでの余白の原因は、Buttonの引数である、contentPaddingを指定していないことです。
contentPaddingを指定しないと、デザインがいい感じになるために、デフォルトで横に24dp,縦に8dp入れてくれています。😠
Button.ktpublic fun Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.shape,
colors: ButtonColors = ButtonDefaults.buttonColors(),
elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
border: BorderStroke? = null,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding, // ←原因!!!!
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable() (RowScope.() -> Unit)
):
しかし、基本的に邪魔なことが多いのでButton実装する時はいつも0dp指定する、で問題ないと思います。
SampleView.kt@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier,
onClick = { /*TODO*/ },
contentPadding = PaddingValues(0.dp) // 追加!!!!
) {
Box(Modifier.size(60.dp), contentAlignment = Alignment.Center) {
Text(
text = "サンプルボタン"
)
}
}
}
}
ボタンのサイズが48dp未満
contentPaddingを0にしても、自動でパディングが付いてしまうことがあります。
問題のあるコード
SampleView.kt@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier,
onClick = { /*TODO*/ },
contentPadding = PaddingValues(0.dp) // 追加!!!!
) {
Box(Modifier.size(30.dp), contentAlignment = Alignment.Center) {
Text(
text = "サンプル"
)
}
}
}
}
size(30dp)を指定しているのに丸いですね🤔
原因と解決策
原因としては、Jetpack Composeでは、インテラクション(タップとか)可能なコンポーザブルが、48dp48dpではない場合、自動的に48dp48dpになるように余白をつけるからです。😠
解決策として、LocalMinimumTouchTargetEnforcementコンポジションというものを使用する方法もありますが、公式は勧めていないので、使わないようにしましょう。
ではどうするのかというと、Button自体にサイズを指定します。
SampleView.kt@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier
.size(30.dp), // 追加!!!!
onClick = { /*TODO*/ },
contentPadding = PaddingValues(0.dp)
) {
Box(Modifier.size(30.dp), contentAlignment = Alignment.Center) {
Text(
text = "サンプル"
)
}
}
}
}
Buttonの中にあるコンポーザブルが幅58dp未満or高さ40dp未満
contentPaddingを0にして、Buttonの中身のサイズを48dp以上だったとしても、余白が付いてしまうことがあります。(Button自体のサイズを指定すれば問題ないですが)
問題のあるコード
↓ 若干ボタンの右に余白がついているのが分かりますかね・・?
@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier,
onClick = { /*TODO*/ },
contentPadding = PaddingValues(0.dp)
) {
Box(Modifier.size(50.dp), contentAlignment = Alignment.Center) {
Text(text = "サ")
}
}
}
}
原因と解決策
原因は、Buttonコンポーザブルにデフォルトで指定されている、最小サイズの指定です。😠
Button.ktRow(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth, // ← 原因!!!!
minHeight = ButtonDefaults.MinHeight // ← 原因!!!!
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
MinWidth→58dp, MinHeight→40dp
defaultMinSizeモディファイアは、制約としては一番弱く、他のminSizeモディファイアが指定されていない時に適用されるものです。
なので、ButtonモディファイアにminSizeの上書きをしてあげれば解決します。
Button.ktRow(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth, // ← 原因!!!!
minHeight = ButtonDefaults.MinHeight // ← 原因!!!!
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
SampleView.kt@Composable
fun SampleView(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Button(
modifier = Modifier
.sizeIn(minWidth = 50.dp, minHeight = 50.dp), // 追加!!!!
onClick = { /*TODO*/ },
contentPadding = PaddingValues(0.dp)
) {
Box(Modifier.size(50.dp), contentAlignment = Alignment.Center) {
Text(text = "サ")
}
}
}
}
Buttonには、こういった直感的でない仕様が入っているので、個人的には、タップ可能なコンポーネントを作る際、Surfaceとかclickableを使って自分でボタンを作るのが好みです。
🙂↕️最後まで読んでいただきありがとうございます🙂↕️