当前位置:   android > 正文

Jetpack Compose 中添加 click 事件的几种方法_compose 点击事件

compose 点击事件

Compose 中添加 click 有多总方法,本文做一个简单总结

1. Modifier.clickable

这是最常见也是最简单的方式,如下所示

Box(
    modifier = Modifier.clickable {
        // 处理点击事件
    }
)
  • 1
  • 2
  • 3
  • 4
  • 5

当点击发生时,除了可以相应事假处理,也会触发水波纹(Ripple)等主题效果。

需要注意,对于 Button 类的 Composable ,不推荐使用 Modifier.clickable,应该使用其自带的 onClick 参数,虽然其内部在调用 Modifier.clickable 之外还有一些额外处理

Button (
	onClick = {
	 	// 处理点击事件
	}) {
	//...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2. Modifier.combinedClickable

在单击事件之外,同时可以处理双击,长按等点击事件

Box(
    modifier = Modifier
        .combinedClickable(
            onClick = {
                // 单击
            },
            onDoubleClick = {
                // 双击
            },
            onLongClick = {
                // 长按
            }
        )
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

与 Modifier.clickable 一样, 点击会触发水波纹效果。

3. Modifier.pointerInput

pointerInput 是 Compose 中处理所有手势事件的入口,类似传统视图的 onTouch 。在这里可以识别 click 手势,而且相应优先级高于 clickable,但是不会触发水波纹之类的效果

Box(
    modifier = Modifier
        .pointerInput(Unit) {
            detectTapGestures(
                onDoubleTap = {
                },
                onLongPress = {
                },
                onPress = {
                },
                onTap = {
                }
            )
        },
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

如上,detectTapGestures 内可以处理点击各种事件。类似的还有 detectDragGestures 可以处理拖动事件。

detectTapGestures 中除了相应事件,还能通过 offset 获知当前点击位置,如下:

detectTapGestures(
    onTap = {
        val x = it.x
        val y = it.y
    },
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此外,当发生 onPress 事件时,还可以获取手指离开时的回调

var pressing by remember { mutableStateOf(false) }

Box(
    modifier = Modifier
        .pointerInput(Unit) {
            detectTapGestures(
                onPress = {
                    // 按下
                    pressing = true

                    val isCanceled = tryAwaitRelease()
                    // 离开

                    pressing = false
                },
            )
        },
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

OnPress 期间,调用 tryAwaitRelease 会挂起当前函数,当手指离开时,继续执行。

tryAwaitRelease 返回一个 bool 值:true 表示手指在当前区域内抬起,false 表示手指移出了当前区域。类似于传统视图的 UP 和 CANCEL 事件。

可见,pointerInput 对事件可以更精细的管理。

4. ViewConfiguration

如果想对事件进一步精细化控制,比如设置点击最小间隔长按超时等,可以使用 ViewConfiguration 进行配置,目前可以设置的项目如下:
在这里插入图片描述
可见,ViewConfiguration 的配置主要影响 combinedClickable 和 pointerInput。

通过 LocalViewConfiguration 可以获得全局默认的 ViewConfiguration。我们可以通过继承和重写的方式,在默认配置基础上实现自定义的 ViewConfiguration 。然后同样借助 CompositionLocal 实现其内部局部 UI 的自定义配置。

下面的例子展示如何自定义长按超时时间:

// 自定义 ViewConfiguration
class CustomViewConfiguration(
    private val defaultViewConfiguration: ViewConfiguration //传入默认配置
) : ViewConfiguration by defaultViewConfiguration {

    // 自定义长按超时3000ms
    override val longPressTimeoutMillis: Long = 3000
}

@Composable
fun Sample() {
    // 获取全局默认 ViewConfiguration
    val defaultViewConfiguration = LocalViewConfiguration.current

	// 基于默认配置创建自定义 CustomViewConfiguration
    val viewConfiguration = remember {
        CustomViewConfiguration(defaultViewConfiguration)
    }

    CompositionLocalProvider(
        LocalViewConfiguration provides viewConfiguration
    ) {
        // 内部的事件配置都受到 CustomViewConfiguration 影响
        Box(
            modifier = Modifier
                .combinedClickable(
                    onLongClick = {
                        // ...
                    },
                )
        )
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

值得一提的是 ViewConfiguration.minimumTouchTargetSize 用来设置手势可响应区域的最小尺寸。这个挺实用,可以解决界面上一些小尺寸控件比艰难点触的问题。 因此,通过设置,有可能 Composable 中 pointerInput 可以相应事件的区域大于其实际渲染的区域。此时取得的 offset 值可能是负数,亦可能超过 Compose 的 size。

minimumTouchTargetSize 默认值是 48.dp,所以如果我们开发中获取了负数 offset 值也不惊奇。

class CustomViewConfiguration(
    private val defaultViewConfiguration: ViewConfiguration
) : ViewConfiguration by defaultViewConfiguration {

    override val minimumTouchTargetSize: DpSize = DpSize(0.dp, 0.dp)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以做个实验,如果将其设置为 0.dp,则永远不会获得负数的 offset 。当然我们不推荐这么做,会造成难点触的情况出现。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/android/detail/39390
推荐阅读
相关标签
  

闽ICP备14008679号