Compose的手势(六)

一、前言

Compose中手势会比在xml的方式要使用更广泛些,所以手势是有必要记录一下的。

二、clickable

Compose中对手势封装了一些单击、双击、长按事件。不过点击事件用的更多一些,这里进行简单的演示

@Composable
fun ClickableSample() {
    val count = remember { mutableStateOf(0) }
    // content that you want to make clickable
    Text(
        text = count.value.toString(),
        modifier = Modifier.clickable { count.value += 1 }
    )
}

三、detectTapGestures

如果想要对基本的手势进行监测,则可以使用PointerInputScope.detectTapGesturesPointerInputScope.detectDragGestures

PointerInputScope.detectTapGestures的大致用法如下:

Modifier.pointerInput(Unit) {
    detectTapGestures(
        onPress = { /* Called when the gesture starts */ },
        onDoubleTap = { /* Called on Double Tap */ },
        onLongPress = { /* Called on Long Press */ },
        onTap = { /* Called on Tap */ }
    )
}

具体示例如下

@Composable
private fun scrollBoxes() {
    Column(
        modifier = Modifier
            .background(Color.LightGray)
            .size(100.dp)
            .verticalScroll(rememberScrollState())
            .pointerInput(Unit){
                detectTapGestures(
                    onPress = { /* Called when the gesture starts */ },
                    onDoubleTap = { /* Called on Double Tap */ },
                    onLongPress = { /* Called on Long Press */ },
                    onTap = { /* Called on Tap */ }
                )
            }
    ) {
        repeat(10) {
            Text("Item $it", modifier = Modifier.padding(2.dp))
        }
    }
}

PointerInputScope.detectDragGestures手势拖动教程可以参考以下链接:

https://developer.android.google.cn/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)

四、Dragging

dragging可以检测手势单一方向拖动,但是并不会移动元素。如果想移动的话可以通过offset来进行移动,如下所示:

var offsetX by remember { mutableStateOf(0f) }
Text(
    modifier = Modifier
        .offset { IntOffset(offsetX.roundToInt(), 0) }
        .draggable(
            orientation = Orientation.Horizontal,
            state = rememberDraggableState { delta ->
                offsetX += delta
            }
        ),
    text = "Drag me!"
)

如果想要控制整个手势拖动,可以pointerInput来进行监测,如下所示:

Box(modifier = Modifier.fillMaxSize()) {
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }

    Box(
        Modifier
            .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
            .background(Color.Blue)
            .size(50.dp)
            .pointerInput(Unit) {
                detectDragGestures { change, dragAmount ->
                    change.consumeAllChanges()
                    offsetX += dragAmount.x
                    offsetY += dragAmount.y
                }
            }
    )
}

五、Swiping

有时候会有滑动切换或者滑动关闭等类似需求,可以使用swipeable修饰符进行实现,该 swipeable修改器允许您将它发布的时候,通常对两个或两个以上的锚点动画中的方向定义的元素。对此的常见用法是实现“滑动到关闭”模式。

需要注意的是,这个修饰符不会移动元素,它只检测手势。您需要保持状态并在屏幕上表示它,例如,通过offset 修改器移动元素 。

swipeable修改器中需要可滑动状态,可以使用 来创建和记住 rememberSwipeableState()。这种状态下还提供了(见以编程动画的一组有用的方法来锚 snapToanimateToperformFling,和 performDrag),以及属性来观察拖动进展。

滑动手势可以配置为具有不同的阈值类型,例如 FixedThreshold(Dp)FractionalThreshold(Float),并且对于每个锚点从到组合,它们可以不同。

为了获得更大的灵活性,您可以配置resistance何时滑动越过边界,并且velocityThreshold即使thresholds尚未到达位置,也可以将滑动动画设置为下一个状态。

 @ExperimentalMaterialApi
    @Composable
    private fun swipeableSample() {
        val width = 96.dp
        val squareSize = 48.dp

        val swipeableState = rememberSwipeableState(0)
        val sizePx = with(LocalDensity.current) { squareSize.toPx() }
        Log.e("YM","sizePx--$sizePx")
        val anchors = mapOf(0f to 0, sizePx to 1) // Maps anchor points (in px) to states

        Box(
            modifier = Modifier
                .width(width)
                .swipeable(
                    state = swipeableState,
                    anchors = anchors,//主要是存储一些滑动状态,可以在其它地方使用
                    thresholds = { _, _ -> FractionalThreshold(0.3f) },//该值表示远离多少时候回弹到原先位置
                    orientation = Orientation.Horizontal //水平
                )
                .background(Color.LightGray)
        ) {
            Box(
                Modifier
                    .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                    .size(squareSize)
                    .background(Color.DarkGray)
            )
        }
    }

第二个swipeable,用来加深对anchors的理解

@ExperimentalMaterialApi
    @Composable
    private fun swipeableSample2() {
        // Draw a slider-like composable consisting of a red square moving along a
// black background, with three states: "A" (min), "B" (middle), and "C" (max).
        val width = 350.dp
        val squareSize = 50.dp

        val swipeableState = rememberSwipeableState("A")
        val sizePx = with(LocalDensity.current) { (width - squareSize).toPx() }
        val anchors = mapOf(0f to "A", sizePx / 2 to "B", sizePx to "C")

        Box(
            modifier = Modifier
                .width(width)
                .swipeable(
                    state = swipeableState,
                    anchors = anchors,
                    thresholds = { _, _ -> FractionalThreshold(0.5f) },
                    orientation = Orientation.Horizontal
                )
                .background(Color.Black)
        ) {
            Box(
                Modifier
                    .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                    .size(squareSize)
                    .background(Color.Red),
                contentAlignment = Alignment.Center
            ) {
                Text(swipeableState.currentValue, color = Color.White, fontSize = 24.sp)
            }
        }
    }

六、多点触控:平移、缩放、旋转

要检测用于平移、缩放和旋转的多点触控手势,您可以使用transformable修饰符。此修改器本身不会变换元素,它只检测手势。

@Composable
fun TransformableSample() {
    // set up all transformation states
    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
            // 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.Blue)
            .fillMaxSize()
    )
}

如果您需要将缩放、平移和旋转与其他手势结合使用,则可以使用 PointerInputScope.detectTransformGestures检测器。

七、事件分发

https://compose.net.cn/design/gesture/custom_gesture/

八、基础事件

上述的事件都是从基础事件封装的,这里简单记录一下基础事件的使用链接,后续完善,可以实现按下时候一个效果,抬起时候一个效果,这种效果上述的几种手势无法完成该操作

  1. Compose实现状态选择器(原生drawable select标签效果) InteractionSource:https://blog.csdn.net/qq_33505109/article/details/124478228
  2. InteractionSource:https://developer.android.google.cn/reference/kotlin/androidx/compose/foundation/interaction/InteractionSource#public-properties_1
  3. 处理用户互动:https://developer.android.google.cn/jetpack/compose/handling-interaction#icon-button-example

八、参考链接

  1. Modifier

    https://developer.android.google.cn/reference/kotlin/androidx/compose/ui/Modifie

  2. 监测手势拖动detectDragGestures

    https://developer.android.google.cn/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)

  3. androidx.compose.material

    https://developer.android.google.cn/reference/kotlin/androidx/compose/material/package-summary

  4. swipeable中的可选修饰符

    https://developer.android.google.cn/reference/kotlin/androidx/compose/material/package-summary#swipeable(androidx.compose.ui.Modifier,androidx.compose.material.SwipeableState,kotlin.collections.Map,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function2,androidx.compose.material.ResistanceConfig,androidx.compose.ui.unit.Dp)

  5. transformable的修饰符说明

https://developer.android.google.cn/reference/kotlin/androidx/compose/foundation/gestures/package-summary?hl=en#(androidx.compose.ui.Modifier).transformable(androidx.compose.foundation.gestures.TransformableState,kotlin.Boolean,kotlin.Boolean)

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值