android 使用交互合成可点击修饰符源中断

68bkxrlz  于 2023-02-11  发布在  Android
关注(0)|答案(1)|浏览(150)
    • 更新**-见问题底部。

我们尝试向每个屏幕定义的stickyTopBar添加内容,解决方案有效。但在下面的示例中,当我们向ActualScreenComposable中的stickyTopBar添加可组合方法时,我们的自定义修饰符clickableWithScaleAnimation会中断。它只是不缩放或单击,但如果我们在它后面添加一个简单的. clickable {},它仍然有效,所以这很奇怪。
我怀疑这个问题与在状态中保存可组合方法的方式有关,但在我们发现这个问题之前,它一直工作得很好。如果我们删除stickyTopBar {...}调用,它就能工作,所以它一定是与状态被设置或处理有关的东西。有什么线索吗?

Scaffold(...) { 
    Column {
        NavigationGraph(...)
    }
}
    
    
fun NavigationGraph(...) {
    val stickyTopBarContent = remember { mutableStateOf<(@Composable () -> Unit)?>(null) }
    
    stickyTopBarContent.value?.let {
        it.invoke()
    }

    AnimatedNavHost {
        screenComposable(actuallScreenConfig, stickyTopBarContent)
        ...
    }
}

fun screenComposable(screenConfig, stickyTopBarContent, ...) {
    if (!screenConfig.supportsStickyTopBar) {
        stickyTopBarContent.value = null
    }
                
    ActualScreenComposable(stickyTopBar = { stickyTopBarContent.value = it }, ...)
}

fun ActualScreenComposable(stickyTopBar: (@Composable () -> Unit) -> Unit, ...) {
    stickyTopBar {
        StickyTopBar() // it even fails with no content in here
    }
    content
}

这是修改器clickableWithScaleAnimation,如果调用了stickyTopBar {...},它将不起作用。

fun content() {
    val coroutineScope = rememberCoroutineScope()
    Column(modifier.clickableWithScaleAnimation(
                coroutineScope = coroutineScope,
                scale = scale,
                scaleDownTo = 0.9f,
                animationDuration = 200,
                onClick = {
                    onSelected(...)
                }
            ))
         // .clickable { onSelected(...) } // this will work if added
            {
            ...
            }
        
}

fun Modifier.clickableWithScaleAnimation(
    interactionSource: MutableInteractionSource = MutableInteractionSource(),
    coroutineScope: CoroutineScope,
    scale: Animatable<Float, AnimationVector1D>,
    animationDuration: Int = 200,
    scaleDownTo: Float = 0.9f,
    onClick: () -> Unit
) = scale(scale.value)
    .clickable(interactionSource = interactionSource, indication = null) {
        coroutineScope.launch {
            scale.animateTo(scaleDownTo, animationSpec = tween(animationDuration))
            onClick()
            scale.animateTo(1f, animationSpec = tween(animationDuration))
        }
    }

我们使用的是Compose 1.3.0

    • 更新1:**

这个问题与clickable修饰符有关。clicked回调函数永远不会被调用。我们的目标只是删除这个指示:

.clickable(interactionSource = interactionSource, indication = null) { ... } // fails
.clickable() { ... } // works

所以在那个特定的修饰语中一定有什么东西以某种方式被打破了--有什么线索吗?

myss37ts

myss37ts1#

可以像这样解决,使用CompositionLocalProvider隐藏指示,然后使用不带参数的clickable修饰符,但它没有解释问题的原因。

fun content() {
    CompositionLocalProvider(LocalIndication provides NoIndication) {
    val coroutineScope = rememberCoroutineScope()
    Column(modifier.clickableWithScaleAnimation(
                coroutineScope = coroutineScope,
                scale = scale,
                scaleDownTo = 0.9f,
                animationDuration = 200,
                onClick = {
                    onSelected(...)
                }
            ))
   }     
}

object NoIndication : Indication {
    private object NoIndicationInstance : IndicationInstance {
        override fun ContentDrawScope.drawIndication() {
            drawContent()
        }
    }

    @Composable
    override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
        return NoIndicationInstance
    }
}

相关问题