androidkotlinandroid-jetpack-composeandroid-jetpack-compose-canvas

How to draw with content side by side in jetpack compose


I am using to drawBehind in my Column. I want to draw side by side. I draw line to specific coordinate and want my Text side of it. I tried this code

@Preview(showBackground = true)
@Composable
fun ItemView() {
    val names = listOf("Captain" to "Vice Captain")
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        itemsIndexed(names) { index, item ->

            var titleCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .drawBehind {
                        val titleBounds = titleCoordinates?.boundsInParent()
                        if (titleBounds != null) {
                            val offset = Offset(x = center.x / 2, y = titleBounds.top)
                            drawLine(
                                color = Color.Black,
                                start = offset,
                                end = offset.copy(y = size.height),
                                strokeWidth = 2.dp.toPx(),
                            )
                        }
                    }
            ) {
                Box(
                    Modifier
                        .padding(top = 24.dp)
                        .onGloballyPositioned { titleCoordinates = it }
                ) {
                    Text(text = item.first, color = Color.Red)
                }
                Text(text = item.second, color = Color.Blue)
            }
        }
    }
}

Actual Output

enter image description here

I can add padding(start = 120.dp) in Column to get my below output. I want to avoid these padding. Is it possible to achieve below output?

Expected Output

enter image description here

Many Thanks


Solution

  • If you you wish to align drawing with actual Content of a Composable you can use Modifier.drawWithContent{}. drawContent() draws what's inside the Composable that this modifier is assigned to while you can position content and drawing based on each other or other requirements.

    enter image description here

    @Preview
    @Composable
    fun ItemView() {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(20.dp)
    
        ) {
            val names = listOf("Captain" to "Vice Captain")
            LazyColumn(modifier = Modifier.fillMaxSize().border(2.dp, Color.Green)) {
                itemsIndexed(names) { index, item ->
    
                    Column(
                        modifier = Modifier
                            .padding(top = 24.dp)
                            .fillMaxWidth()
                            .drawWithContent {
    
                                translate(
                                    left= 120.dp.toPx(), top = 0f
                                ){
                                    drawLine(
                                        color = Color.Black,
                                        start = Offset(0f,0f),
                                        end = Offset(0f, size.height),
                                        strokeWidth = 2.dp.toPx(),
                                    )
    
                                    translate(
                                        left= 10.dp.toPx(), top = 0f
                                    ){
                                        this@drawWithContent.drawContent()
                                    }
    
                                }
                            }
    
    
                    ) {
                        Text(text = item.first, color = Color.Red)
                        Text(text = item.second, color = Color.Blue)
                    }
                }
            }
        }
    }