概要
ViewConfiguration.minimumTouchTargetSizeは設定された範囲内のコンポーネントの最小のタッチエリアを指定する。
コンポーネントのサイズより大きな範囲を最小のタッチエリアとして指定することもできるため、タッチエリアと近隣のコンポーネントの領域が仕組み上被りうる。
領域が被ったコンポーネントにクリックイベントが設定されている場合、ViewConfiguration.minimumTouchTargetSizeで拡張されたタッチエリアではなく近隣コンポーネントのクリックイベントが優先される。
検証している限りこの優先順位はコンポーネントの宣言順の影響は受けない。
詳細
ViewConfiguration.minimumTouchTargetSizeとは
ViewConfigurationとは、ロングプレスがタイムアウトする時間や、スクロールやスワイプの判定の閾値を設定できるinterfaceです。JetpackCpmposeのために用意されたinterfaceではなく、AndroidViewから存在しています。AndroidViewや、JetpackComposeといったレイヤの話ではなくシステム側に干渉できるinterfaceとなります。
この中にminimumTouchTargetSizeという項目があり、UIの最小タッチエリアを指定できます。デフォルトでは縦横48dpに指定されている。この48という数字はMaterial Designで指定されているタッチエリアの最小領域です。他のUIに関するinterface、例えばModifier.minimuminteractivecomponentsizeでも同様の数字が指定されており、統一的に使用されている数字だとわかります。詳しくはドキュメントを参照してください。
https://m3.material.io/foundations/designing/structure#b421e522-35a6-47cd-bfc6-bf94cbacf7bb
https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).minimumInteractiveComponentSize()
ビジュアルイメージ
赤いボックス、青いボックスを横並びに表示する。
クリックした領域に応じてトーストが表示される。

コード
以下のようなコードで、赤いボックス、青いボックスを横並びに表示する。
minimumTouchTargetSizeを縦横500dpで上書きしたViewConfigurationを使って緑のボックスを囲んでいる。
val context = LocalContext.current
val defaultViewConfiguration = LocalViewConfiguration.current
class CustomViewConfiguration : ViewConfiguration by defaultViewConfiguration {
override val minimumTouchTargetSize: DpSize
get() = DpSize(500.dp, 500.dp)
}
val customViewConfiguration = CustomViewConfiguration()
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.Blue)
.clickable {
Toast.makeText(
context,
"青クリック",
Toast.LENGTH_SHORT
).show()
},
)
CompositionLocalProvider(
LocalViewConfiguration provides customViewConfiguration
) {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.Green)
.clickable {
Toast
.makeText(context, "緑クリック", Toast.LENGTH_SHORT)
.show()
}
)
}
}
挙動
この時、青い箱以外の全ての範囲どこをクリックしても緑の箱のタッチエリアとなる。が青い箱のエリアだけはタッチエリアを奪えない。