Home > Software engineering >  zIndex is not refeshing as result of state change
zIndex is not refeshing as result of state change

Time:05-03

I managed to work this out, and setup 3 cards one on top of the other as seperate boxs compose elements with onclick and on drag properties. The issue is now, that I'd like the card that I'm pressing/dragging to set to the front, so, I played with the z-index modifier, but, it looks like I'm doing something wrong. Any idea?

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Test1Theme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {

                    for (i in 1 until 4) {
                        DraggableBox(title = "Box_${ 1}", initX = 100f*i.toFloat(), initY = 100f, content =
                        {
                            Text(text = "Box_${i}", color = Color.White, fontSize = 16.sp, textAlign = TextAlign.Center)
                        }
                        )
                    }
                }
            }
        }
    }
}

@Composable
fun DraggableBox(title: String, initX: Float = 0f, initY: Float = 0f, content: @Composable() () -> Unit) {
    val cardInitWidth = 135f
    val cardInitHeight = 190f
    val expandValue = 20f

    Box(
        modifier = Modifier
            .fillMaxSize()
    ) {
        val shape = RoundedCornerShape(12.dp)
        val coroutineScope = rememberCoroutineScope()
        val enable = remember { mutableStateOf(true) }
        var offsetX  =  remember { Animatable(initialValue = initX) }
        var offsetY  =  remember { Animatable(initialValue = initY) }
        val interactionSource = remember { MutableInteractionSource() }
        val clickable = Modifier.clickable(
            interactionSource = interactionSource,
            indication = LocalIndication.current
        ) { }
        val isPressed by interactionSource.collectIsPressedAsState()
        val size = animateSizeAsState(
            targetValue = if (enable.value && !isPressed) {
                Size(width = cardInitWidth, height = cardInitHeight)
            } else {
                Size(width = cardInitWidth   expandValue, height = cardInitHeight   expandValue)
            }
        )
        Box(
            Modifier
                .offset {
                    IntOffset(
                        x = offsetX.value.roundToInt(),
                        y = offsetY.value.roundToInt()
                    )
                }
                .zIndex(zIndex = if (enable.value && !isPressed) 5f else 0f)
                .size(size.value.width.dp, size.value.height.dp)
                .clip(shape)
                //.background(Color(0xFF5FA777))
                .background(color = MaterialTheme.colors.primary)
                .border(BorderStroke(2.dp, Color.Black), shape = shape)
                .pointerInput(Unit) {
                    detectDragGestures(
                        onDragStart = {
                            enable.value = !enable.value
                        },
                        onDrag = { change, dragAmount ->
                            change.consumeAllChanges()
                            coroutineScope.launch {
                                offsetX.snapTo(targetValue = offsetX.value   dragAmount.x)
                                offsetY.snapTo(targetValue = offsetY.value   dragAmount.y)
                            }
                            spring(stiffness = Spring.StiffnessHigh, visibilityThreshold = 0.1.dp)

                        },
                        onDragEnd = {
                            enable.value = !enable.value
                            spring(stiffness = Spring.StiffnessLow, visibilityThreshold = 0.1.dp)
                            coroutineScope.launch {
                                launch {
                                    offsetY.animateTo(
                                        targetValue = initY,
                                        animationSpec = tween(
                                            durationMillis = 700,
                                            delayMillis = 50,
                                            easing = LinearOutSlowInEasing
                                        )
                                    )
                                }
                                offsetX.animateTo(
                                    targetValue = initX,
                                    animationSpec = tween(
                                        durationMillis = 700,
                                        delayMillis = 50,
                                        easing = LinearOutSlowInEasing
                                    )
                                )
                            }
                        }
                    )
                }
                .then(clickable)
        ) {
            Row  (modifier = Modifier
                .fillMaxHeight(),
                verticalAlignment = Alignment.CenterVertically
            )
            {
                Column (modifier = Modifier
                    .fillMaxWidth(),
                    horizontalAlignment = Alignment.CenterHorizontally
                )
                {
                    Column (
                        horizontalAlignment = Alignment.CenterHorizontally
                    )
                    {
                        Text(text = "init-X: ${initX.toString()}", color = Color.White, fontSize = 16.sp, textAlign = TextAlign.Center)
                        Text(text = "init-Y: ${initY.toString()}", color = Color.White, fontSize = 16.sp, textAlign = TextAlign.Center)
                    }
                    Column (
                        horizontalAlignment = Alignment.CenterHorizontally
                    )
                    {
                        Text(text = "offset-X: ${offsetX.value.roundToInt().toString()}", color = Color.White, fontSize = 16.sp, textAlign = TextAlign.Center)
                        Text(text = "offset-Y: ${offsetY.value.roundToInt().toString()}", color = Color.White, fontSize = 16.sp, textAlign = TextAlign.Center)
                    }
                    Column (
                        horizontalAlignment = Alignment.CenterHorizontally
                    )
                    {
                        content()
                    }
                }
            }
        }
    }
}

CodePudding user response:

The Modifier.zIndex works only for children within the same parent.

In your case you should move this modifier to the topmost Box. To do so you have to move enable and isPressed one level up too, and I would move all the other variables as well - but that's just a matter of taste, I guess.

val enable = remember { mutableStateOf(true) }
val isPressed by interactionSource.collectIsPressedAsState() 

Box(
    modifier = Modifier
        .fillMaxSize()
        .zIndex(zIndex = if (enable.value && !isPressed) 5f else 0f)
) {
    // ...   
  • Related