[ Compose ] Handle Tap Press Drag Scroll Swipe Transform Events
[ Compose ] Handle Tap Press Drag Scroll Swipe Transform Events
Handle Click Events
key apis are clickable Modifier
@Composable
private fun ClickableItem() {
Box(Modifier.background(Color.Yellow).clickable {
println("Clicked")
}) { Text("Hello") }
}
@Preview
@Composable
fun Compose15() {
ClickableItem()
}
Handle Press Events
key apis are pointerInput detectTapGestures
@Composable
private fun DetectGestures() {
Box(Modifier.background(Color.Yellow).pointerInput(Unit) {
detectTapGestures(
onTap = { println("OnTap $it") },
onDoubleTap = { println("onDoubleTap $it") },
onPress = { println("onPress $it") },
onLongPress = { println("onLongPress $it") }
)
}) { Text("Hello") }
}
@Preview
@Composable
fun Compose16() {
DetectGestures()
}
Handle Drag Events
key apis are draggable rememberDraggableState
background must set after offset, otherwise offset will not applied to background
@Composable
private fun Draggable() {
Box(Modifier.background(Color.Red).width(300.dp).height(200.dp)) {
var offsetX by remember { mutableFloatStateOf(0f) }
var parentWidth by remember { mutableFloatStateOf(0f) }
var elementWidth by remember { mutableFloatStateOf(0f) }
val minOffset by remember {
derivedStateOf { (elementWidth - parentWidth) / 2 }
}
val maxOffset by remember {
derivedStateOf { (parentWidth - elementWidth) / 2 }
}
Text(
text = "Hello",
modifier = Modifier.offset {
println("$offsetX $minOffset $maxOffset")
IntOffset(offsetX.coerceAtLeast(minOffset).coerceAtMost(maxOffset).roundToInt(), 0)
}.draggable(
orientation = Orientation.Horizontal,
state = rememberDraggableState { delta ->
offsetX = (offsetX + delta).coerceAtLeast(minOffset).coerceAtMost(maxOffset)
}
).onGloballyPositioned { coordinates ->
elementWidth = coordinates.size.width.toFloat()
parentWidth = coordinates.parentLayoutCoordinates!!.size.width.toFloat()
}.background(Color.Yellow).align(Alignment.Center)
)
}
}
@Preview
@Composable
fun Compose17() {
Draggable()
}
Handle Drag Events on Multiple Directions
key apis are pointerInput detectDragGestures
@Composable
private fun Draggable() {
Box(Modifier.background(Color.Red).width(300.dp).height(200.dp)) {
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }
val minOffset = (-100).dp
val maxOffset = 100.dp
Box(
Modifier.width(100.dp).height(100.dp).offset {
IntOffset(
offsetX.coerceAtLeast(minOffset.toPx()).coerceAtMost(maxOffset.toPx()).roundToInt(),
offsetY.coerceAtLeast(minOffset.toPx()).coerceAtMost(maxOffset.toPx()).roundToInt()
)
}.pointerInput(Unit) {
detectDragGestures { change, amount ->
change.consume()
offsetX = (offsetX + amount.x).coerceAtLeast(minOffset.toPx()).coerceAtMost(maxOffset.toPx())
offsetY = (offsetY + amount.y).coerceAtLeast(minOffset.toPx()).coerceAtMost(maxOffset.toPx())
}
}.background(Color.Yellow).align(Alignment.Center)
)
}
}
@Preview
@Composable
fun Compose18() {
Draggable()
}
Handle Scroll Event
key apis are horizontalScroll verticalScroll rememberScrollState
by default scroll range is area size of box content
both horizontalScroll and verticalScroll are implemented based on scrollable Modifier
@Composable
private fun ScrollBar() {
val gradient1 = Brush.verticalGradient(colors = listOf(Color.Red, Color.Yellow, Color.Red))
val gradient2 = Brush.verticalGradient(colors = listOf(Color.Blue, Color.Green, Color.Blue))
val gradient3 = Brush.verticalGradient(colors = listOf(Color.Black, Color.White, Color.Black))
Box(Modifier.background(gradient1).width(400.dp).height(200.dp).verticalScroll(rememberScrollState())) {
Column(Modifier.background(gradient2).width(300.dp).height(300.dp).align(Alignment.Center).verticalScroll(rememberScrollState())) {
Box(Modifier.background(gradient3).width(200.dp).height(600.dp).align(Alignment.CenterHorizontally))
}
}
}
@Preview
@Composable
fun Compose19() {
ScrollBar()
}
Handle Swipe Event
key apis are swipeable offset rememberSwipeableState
background must set after offset, otherwise offset will not applied to background
swipeable is implemented based on draggable Modifier
@Composable
@OptIn(ExperimentalMaterialApi::class)
private fun Swipe() {
val swipeState = rememberSwipeableState(0f)
val endPosition = with(LocalDensity.current) { 80.dp.toPx() }
val anchors = mapOf(0f to 0f, endPosition to 1f)
Box(Modifier.width(200.dp).swipeable(
state = swipeState,
anchors = anchors,
orientation = Orientation.Horizontal,
thresholds = { from, to -> FractionalThreshold(0.5f) }
).background(Color.Yellow)) {
val gradient = Brush.horizontalGradient(colors = listOf(Color.Black, Color.White, Color.Black))
Box(Modifier.size(100.dp).offset {
println(swipeState.currentValue)
IntOffset(swipeState.offset.value.roundToInt(), 0)
}.background(gradient))
}
}
@Preview
@Composable
fun Compose21() {
Swipe()
}
- anchors, decide where can stop, and corresponding states at stop points
- SwipeableState, save states at current offset
- thresholds, decide the threshold for auto-swipe-to-target or swipe-back-to-initial
Handle Transform Event
Transform means transfrom through multi-pointer-touch here
that is, scale translate rotate by multi-finger gestures
key apis are transformable rememberTransformableState graphicsLayer
@Composable
private fun MultiFingerTouch() {
var scale by remember { mutableFloatStateOf(1f) }
var rotation by remember { mutableFloatStateOf(0f) }
var translation by remember { mutableStateOf(Offset.Zero) }
val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
scale *= zoomChange
rotation += rotationChange
translation += offsetChange
}
Box(Modifier.width(250.dp).height(250.dp).graphicsLayer {
scaleX = scale
scaleY = scale
translationX = translation.x
translationY = translation.y
rotationZ = rotation
}.transformable(state).background(Color.Yellow))
}
@Preview
@Composable
fun Compose22() {
MultiFingerTouch()
}
更多推荐



所有评论(0)