onTap - 使用相同的代码和状态提升,检测TapGestures 无法作为可点击正常工作

Kin*_*356 1 android-jetpack android-jetpack-compose

我有一个方法“活动”,它托管一个“屏幕”,并且由于状态提升很酷,所以我这样做了,但遇到了问题。

虽然使用Modifier.clickable代码可以完美运行(增加值) ,但使用detectorTapGestures::onTap 时,相同的代码无法正常运行, 如通过Log.d("ExampleScreen", "onClick Multi Count is $multiCount")观察到的那样

@Composable
fun ExampleActivity() {
    var multiCount by remember {
        mutableStateOf(0)
    }

    Log.d("ExampleActivity", "Multi Count is $multiCount") //this works either way

    ExampleScreen(
        multiCount = multiCount,
        incrementMultiCount = {
            multiCount = ++multiCount
        }
    )
}

  @Composable
    fun ExampleScreen(
        modifier: Modifier = Modifier,
        multiCount: Int,
        incrementMultiCount: () -> Unit
    ) {
            Log.d("ExampleScreen", "Example Multi Count is $multiCount") //this works either way
            Column(
                modifier = modifier
                    .fillMaxSize()
                    .padding()
            ) {
    
                Text(
                    modifier = Modifier
                        .size(100.dp, 50.dp)
                        .background(MaterialTheme.colorScheme.primaryContainer)
                        .clickable {//this works
                            incrementMultiCount()
                            Log.d("ExampleScreen", "onClick Multi Count is $multiCount")
                        }
           /*             .pointerInput(Unit) { //this does not work
                            detectTapGestures(
                                onTap = {
                                    incrementMultiCount()
                                    Log.d("ExampleScreen", "onClick Multi Count is $multiCount") //this stays 0
                                },
                                onLongPress = {
    
                                }
                            )
                        }*/, text = "Click to confirm"
                )
            }
    }
Run Code Online (Sandbox Code Playgroud)

部分地,它的工作原理与ExampleActivityExampleScreen函数体中定义的日志中所示相同(递增工作但不读取值),但在onTapGesture中却不然

如果记住值直接位于 ExampleScreen 可组合项中,则 onTap 和 clickable 可以完美工作,但不是我想要的。

最后,在建议我使用有效的方法之前,我想使用 detectorTapGestures,因为我确实需要 LongPress 方法来进行辅助工作

另外,我非常感谢您的解释,因为我认为两者的工作原理相同

Jan*_*ína 5

您必须将回调包装在 中rememberUpdatedState,如下所示:

val onTap: () -> Unit = {
    incrementMultiCount()
    Log.d("ExampleScreen", "onClick Multi Count is $multiCount")
}
val updatedOnTap = rememberUpdatedState(onTap)

detectTapGestures(onTap = { updatedOnTap.value.invoke() })
Run Code Online (Sandbox Code Playgroud)

这也是.clickable修饰符对其onClick参数所做的事情,您可以在其源代码中看到这一点。可以在文档中找到解释rememberUpdatedState

rememberUpdatedState当组合过程中计算的参数或值被长期存在的 lambda 或对象表达式引用时,应使用该方法。重组将更新结果,State而无需重新创建长期存在的 lambda 或对象,从而允许该对象持续存在,而无需取消和重新订阅,或者重新启动可能成本高昂或无法重新创建和重新启动的长期操作。

顺便说一句,还有Modifier.combinedClickable可以用于长按检测的。