Home > other >  Trigger click effect when another component is clicked in jetpack compose
Trigger click effect when another component is clicked in jetpack compose

Time:10-19

I have a card in a row. Both are clickable, but when I click either one of them I want the other to trigger the click effect also.

Is it possible to do this?

enter image description here

This is my code so far

@ExperimentalMaterialApi
@Composable
fun GlobalSettingItem(
    iconDrawable: Int,
    title: Int,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(enabled = true, onClick = onClick),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Start,
    ) {
        Card(
            modifier = Modifier
                .padding(start = 16.dp, top = 4.dp, bottom = 8.dp)
                .size(50.dp),
            backgroundColor = MaterialTheme.myTheme.background,
            shape = CircleShape,
            onClick = { },
            elevation = 0.dp,
        ) {
            Box(contentAlignment = Alignment.Center) {
                Icon(
                    painter = painterResource(id = iconDrawable),
                    contentDescription = "Settings Icon",
                    tint = MaterialTheme.myTheme.colorAccent,
                    modifier = Modifier
                        .width(24.dp)
                        .height(24.dp),
                )
            }
        }
        Text(
            modifier = Modifier.padding(start = 4.dp),
            text = stringResource(title),
            color = MaterialTheme.myTheme.onBackground,
            style = TextStyle(fontSize = 16.sp),
            )
    }
}

CodePudding user response:

To synchronize the "click effect" in multiple Composables you need to share the same InteractionSource object between them, so they can react to the same state.
By default every clickable element creates (and remembers) their state separately, but you can always pass it to it, from the outside if you wish to have more control over it.

Both Modifier.clickable and Card have variants where you can pass interactionSource. In clickable you also need to pass indication, because that parameter has no default value (like in Card), but that value is just taken from LocalIndication.current.

I think you should also assign your onClick in Card, otherwise it would consume clicks and do nothing with it. Which is probably not what you want, but I'm not sure about your intention here.

@ExperimentalMaterialApi
@Composable
fun GlobalSettingItem(
    iconDrawable: Int,
    title: Int,
    onClick: () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(
                enabled = true,
                interactionSource = interactionSource,
                indication = LocalIndication.current,
                onClick = onClick
            ),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Start,
    ) {
        Card(
            modifier = Modifier
                .padding(start = 16.dp, top = 4.dp, bottom = 8.dp)
                .size(50.dp),
            backgroundColor = MaterialTheme.myTheme.background,
            shape = CircleShape,
            interactionSource = interactionSource,
            onClick = onClick,
            elevation = 0.dp,
        ) {
            Box(contentAlignment = Alignment.Center) {
                Icon(
                    painter = painterResource(id = iconDrawable),
                    contentDescription = "Settings Icon",
                    tint = MaterialTheme.myTheme.colorAccent,
                    modifier = Modifier
                        .width(24.dp)
                        .height(24.dp),
                )
            }
        }
        Text(
            modifier = Modifier.padding(start = 4.dp),
            text = stringResource(title),
            color = MaterialTheme.myTheme.onBackground,
            style = TextStyle(fontSize = 16.sp),
        )
    }
}
  • Related