Closed4
Composeの"Tap and press"を読む

単純なタップ
お馴染みのclickable
Box(
modifier = Modifier
.background(Color.Blue)
.fillMaxSize()
.clickable { Log.d("@@@", "onClick") }
)
長いタップ
押したタイミングでonClick
がcallされ、少し経つとonLongClick
がcallされる。
Box(
modifier = Modifier
.fillMaxSize()
.combinedClickable(
onClick = {
Log.d("@@@", "onClick")
},
onLongClick = {
Log.d("@@@", "onLongClick")
},
onLongClickLabel = "test"
)
)

長押しの場合はHapticFeedbackがベストプラクティス
val haptic = LocalHapticFeedback.current
Box(
modifier = Modifier
.fillMaxSize()
.combinedClickable(
onClick = {
Log.d("@@@", "onClick")
},
onLongClick = {
Log.d("@@@", "onLongClick")
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
},
onLongClickLabel = "test"
)
)

pointerInput
のdetectTapGestures
エフェクトなしでclickしたい場合はModifier.clickable
は視覚的なエフェクトがかかり、ユーザがタップしたことが分かりやすい感じになっている。ただそのエフェクトが邪魔な時もある。その場合は以下のようにする。
Box(
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures {
Log.d("@@@", "Taped!")
}
}
)

calculateOffsetの計算は自前でやらないといけないがダブルタップした箇所をフォーカスするようなケースの場合、detectTapGestures#onDoubleTap
は有用。
var zoomed by remember { mutableStateOf(false) }
var zoomOffset by remember { mutableStateOf(Offset.Zero) }
Image(
painter = rememberAsyncImagePainter(model = photo.highResUrl),
contentDescription = null,
modifier = modifier
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { tapOffset ->
zoomOffset = if (zoomed) Offset.Zero else
calculateOffset(tapOffset, size)
zoomed = !zoomed
}
)
}
.graphicsLayer {
scaleX = if (zoomed) 2f else 1f
scaleY = if (zoomed) 2f else 1f
translationX = zoomOffset.x
translationY = zoomOffset.y
}
)
このスクラップは2023/09/29にクローズされました