Search code examples
canvasandroid-jetpack-composedraw

Android Jetpack Compose draw rectangle by the full height and width of its parent layout


I am trying to draw a round rectangle based on the height and width of its parent.

The below code snippet draws the rectangle but its not filling the whole box

{
    val localDensity = LocalDensity.current

    var height by remember {
        mutableStateOf(0. dp)
    }

    var width by remember {
        mutableStateOf(0. dp)
    }

    Box(modifier = modifier
        .onGloballyPositioned {
            lc - >
                height = with(localDensity) {
                    lc.size.height.toDp()
                }
            width = with(localDensity) {
                lc.size.width.toDp()
            }
        }) {

        drawRect(size = Size(width = width.value, height = height.value), color = Color.Green)

        Column() {
            Text(

                text = "H $height",


            )
            Text(

                text = "W $width",


            )
        }

    }

}

I want the canvas to draw the rectangle, using the full height and width of the box, I am populating this in a grid like column and row , as below.

I don't want to use filling the Box layout background, I want to

Example Image


Solution

  • What's wrong in your code is you are converting size in px to dp while drawRect function requires Size which has width and height params as Float in px. Let's say your screen is 1000x1000 and density 2. When you convert to dp and get dp.value, this is 2f if it's 2.dp, you can only draw 500x500 rect while your parent size is 1000x1000px

    You can also do it with Modifier.onSizeChanged{} as

    val localDensity = LocalDensity.current
    
    var size by remember {
        mutableStateOf(Size.Zero)
    }
    
    
    Box(modifier = Modifier
    
        .onSizeChanged {
            size = localDensity.run { it.toSize() }
        }
        .drawBehind {
            drawRect(size = size, color = Color.Green)
        }
    
    ) {
    }
    

    If you don't need to size in any place you can draw it as below either

    Box(modifier = Modifier
        .drawBehind {
            drawRect(color = Color.Green)
        }
    
    ) {
    }
    

    Modifier.drawBehind's param is onDraw: DrawScope.() -> Unit, has DrawScope receiver which returns size of the Composable its set to. Default size for drawRect is size from DrawScope.