An overview of

Compose provides several apis for implementing various gestures, including click, press, double click, long press, horizontal and vertical swipe, drag, two-finger pan, zoom and rotate, and nested happy effects

All kinds of gesture effect introduction

Click on the sign

code

Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Box(modifier = Modifier
            .size(200.dp)
            .background(Color.Green)
            .clickable {
                App.toast("Clicked")
            }, contentAlignment = Alignment.Center
        ) {
            Text(text = "Click event")}}Copy the code

The effect

Single click, press, double click, and long press

code

@Composable
fun PointerView(a) {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Box(
            modifier = Modifier
                .size(200.dp)
                .background(Color.Green)
                .pointerInput(Unit) {
                    detectTapGestures(
                        onTap = {
                            App.toast("Single point event trigger")
                        },
                        onDoubleTap = {
                            App.toast("Double click event")
                        },
                        onPress = {
// app.toast (" press event ")
                        },
                        onLongPress = {
                            App.toast("Long press event")
                        }
                    )
                }, contentAlignment = Alignment.Center
        ) {
            Text(text = "Single click, double click, press, long press events")}}}Copy the code

instructions

Double click, click, long press will trigger the effect of press callback, pointerInput. DetectTapGestures

The effect

Horizontal and vertical sliding

code

val list = (0.255.)
    Column(
        Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
    ) {
        Box(
            Modifier
                .fillMaxWidth(10f)
                .height(100.dp)
                .background(Color.Green)
                .horizontalScroll(rememberScrollState()),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "Ananzhuo, welcome to follow the nuggets, public number, CSDN, share android knowledge, ananzhuo, welcome to follow the nuggets, public number, CSDN, share android knowledge, ananzhuo, welcome to follow the nuggets, public number, CSDN, share Android knowledge",
                style = TextStyle(color = Color.White, fontSize = 20.sp, fontWeight = FontWeight.Bold)
                )
        }

        repeat(40) {
            Box(
                Modifier
                    .height(80.dp)
                    .fillMaxWidth()
                    .background(Color(list.random(), list.random(), list.random())),
                contentAlignment = Alignment.Center
            ) {
                Text(text = it.toString(), style = TextStyle(color = Color.White, fontSize = 20.sp))
            }
        }
    }
Copy the code

instructions

For any control, you only need to invoke two modifiers to achieve the sliding effect

.verticalScroll(rememberScrollState())

.horizontalScroll(rememberScrollState())

The effect

drag

code

var offsetX by remember {
        mutableStateOf(0f)}var offsetY by remember {
        mutableStateOf(0f)
    }
    Box(Modifier.fillMaxSize()) {
        Box(
            Modifier
                .offset { IntOffset(offsetX.toInt(), offsetY.toInt()) }
                .size(200.dp)
                .background(Color.Green, shape = CircleShape)
                .pointerInput(Unit) {
                    detectDragGestures(onDrag = { pointerInputChange: PointerInputChange, offset: Offset ->
                        pointerInputChange.consumeAllChanges()// Consumption slide
                        offsetX += offset.x
                        offsetY += offset.y
                    })
                },
            contentAlignment = Alignment.Center
        ) {
            Text(text = "Tap slide circle")}}Copy the code

instructions

The effect

Multistage sliding

code

val list = (0.255.)

    val width = 300.dp
    val squareSize = 60.dp

    val swipeableState = rememberSwipeableState(0)
    val sizePx = with(LocalDensity.current) { squareSize.toPx() }
    val anchors = mapOf(
        0f to 0,
        sizePx to 1,
        sizePx * 2 to 2,
        sizePx * 3 to 3,
        sizePx * 4 to 4
    ) // Maps anchor points (in px) to states

    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Row(
            Modifier
                .width(width)
                .height(squareSize)) {
            repeat(5) {
                Box(
                    Modifier
                        .width(squareSize)
                        .fillMaxHeight()
                        .background(color = Color(list.random(), list.random(), list.random()))
                )
            }
        }
        Box(
            modifier = Modifier
                .width(width)
                .swipeable(
                    state = swipeableState,
                    anchors = anchors,
                    thresholds = { _, _ -> FractionalThreshold(0.3 f)}, orientation = Orientation.Horizontal ) ) { Box( Modifier .offset { IntOffset(swipeableState.offset.value.roundToInt(),0) }
                    .width(squareSize)
                    .height(200.dp)
                    .background(Color.Yellow)
            ){
                Text(text = "Slide slider")}}}Copy the code

instructions

This is an experimental code

The key code here is as follows: This anchors separates the parent container into five sections, and when the slide ends, the slide control automatically pans to the appropriate area.

 val anchors = mapOf(
        0f to 0,
        sizePx to 1,
        sizePx * 2 to 2,
        sizePx * 3 to 3,
        sizePx * 4 to 4
    )
Copy the code

The effect

Two-finger gestures (pan, zoom, rotate)

code

var scale by remember { mutableStateOf(1f)}var rotation by remember { mutableStateOf(0f)}var offset by remember { mutableStateOf(Offset.Zero) }
    val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
        scale *= zoomChange
        rotation += rotationChange
        offset += offsetChange
    }
    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Box(
            Modifier
                // apply other transformations like rotation and zoom
                // on the pizza slice emoji
                .graphicsLayer(
                    scaleX = scale,
                    scaleY = scale,
                    rotationZ = rotation,
                    translationX = offset.x,
                    translationY = offset.y
                )
                // add transformable to listen to multitouch transformation events
                // after offset
                .transformable(state = state)
                .background(Color.Green)
                .fillMaxSize(0.5 f),
            contentAlignment = Alignment.Center
        ){
            Text(text = "Two-finger manipulation, translation, scaling, Z-rotation, one-finger manipulation will not work.", color = Color.White)
        }
    }


Copy the code

instructions

The effect

Nested slide effects

code

val toolbarHeight = 48.dp/ / Topbar height
    val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }// Convert topbar height to px
    val toolbarOffsetHeightPx =
        remember { mutableStateOf(0f)}// Dynamic vertical translation distance of topbar
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                val delta = available.y
                val newOffset = toolbarOffsetHeightPx.value + delta// Update topbar's dynamic translation distance
                toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)// Keep the translation distance of topbar between (-toolbarheightpx, 0f)
                return Offset.Zero
            }
        }
    }
    Box(
        Modifier
            .fillMaxSize()
            .nestedScroll(nestedScrollConnection)
    ) {
        LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
            items(100) { index ->
                Text("I'm item $index", modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp))
            }
        }
        TopAppBar(
            modifier = Modifier
                .height(toolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
            title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}")})}Copy the code

instructions

The effect

Git address: github.com/ananananzhu…