Home > front end >  How to exclude a child composable from parent alpha value change?
How to exclude a child composable from parent alpha value change?

Time:01-15

In the shopping list item composable, I am reducing the alpha value on the whole item by changing the alpha value on it's parent Row composable, but I want to exclude a child Icon composable from receiving the parent Row's alpha change and retain a 100% alpha value. I set the modifier on the child Icon to alpha(1f), but it is not working. The alpha change on the parent is also propagating to the child despite this. Is it possible exclude the child from the parent's alpha change?

Composable

@Composable
fun ShoppingListScreenItem(
    rowModifier: Modifier = Modifier,
    item: ShoppingListItem,
    mainViewModel: ShoppingListScreenViewModel,
    onNavigateToAddEditItemScreenFromItemStrip: (ShoppingListItem) -> Unit,
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(start = 3.dp, bottom = 5.dp)
            .then(rowModifier)
            .alpha(if (item.isItemDisabled) 0.35f else 1f)
            .clickable {
                onNavigateToAddEditItemScreenFromItemStrip(item)
            },
        verticalAlignment = Alignment.CenterVertically,
    ) {
        ...
     
        if(mainViewModel.shoppingListState.value!!.sortOrder != "Custom" && !item.isInCart) {

            //I want to exclude this child composable
            IconToggleButton(
                checked = item.isItemDisabled,
                onCheckedChange = {
                    scope.launch {
                        mainViewModel.updateShoppingListItemDisabledInDb(item, it)
                    }
                },
            ) {
                Icon(
                    modifier = Modifier.alpha(1f).size(26.dp),
                    painter = painterResource(id = R.drawable.baseline_disabled_visible_24),
                    contentDescription = "Toggle disable the item strip",
                )
            }
        }
    }
}

CodePudding user response:

This can be achieved using Layout and placeable.placeWithLayer and Modifier.layoutId to select which Composable is to be used with default alpha as.

This is a custom Column, you can customize Layout as required, purpose is to show Modifier.layoutId usage and Placeable.placeRelativeWithLayer to apply any desired graphic layer property to specific Composable in layout phase.

Result

enter image description here

Usage

MyLayout(
    alpha = .5f
) {
    Text("Default Alpha", fontSize = 20.sp)
    Text("Default Alpha", fontSize = 20.sp)
    Text("Custom Alpha", fontSize = 20.sp), modifier = Modifier.layoutId("full_alpha"))
    Text("Default Alpha", fontSize = 20.sp)

    Image(painter = painterResource(id = R.drawable.landscape5), contentDescription = "")
}

Implementation

@Composable
private fun MyLayout(
    modifier: Modifier = Modifier,
    alpha: Float = 1f,
    content: @Composable () -> Unit
) {

    val measurePolicy = MeasurePolicy { measurables, constraints ->

        val fullAlphaIndex = measurables.indexOfFirst {
            it.layoutId == "full_alpha"
        }
        val placeablesWidth = measurables.map { measurable ->
            measurable.measure(constraints)
        }

        val hasBoundedWidth = constraints.hasBoundedWidth
        val hasFixedWidth = constraints.hasFixedWidth


        val width =
            if (hasBoundedWidth && hasFixedWidth) constraints.maxWidth
            else placeablesWidth.maxOf { it.width }

        val height = placeablesWidth.sumOf {
            it.height
        }

        var posY = 0

        layout(width, height) {
            placeablesWidth.forEachIndexed { index, placeable ->
                placeable.placeRelativeWithLayer(0, posY) {
                    if (index == fullAlphaIndex) {
                        this.alpha = 1f
                    } else {
                        this.alpha = alpha
                    }
                }

                posY  = placeable.height
            }
        }

    }

    Layout(
        modifier = modifier,
        content = content,
        measurePolicy = measurePolicy
    )
}
  • Related