androidkotlinandroid-jetpack-composelazycolumnandroid-jetpack-compose-modifier

How to set a drawable object instance as a background of a LazyColumn?


I mean a Drawable generated dinamically, not a file from res/drawable.

I tryed setting it as a background of the modifier, but it doesn't accept a Drawable instance object. In java, it was done like this: layout.setBackground(bg.getDrawable())

In this case, I have a LazyColumn, and it haves some items. Ok, I need the drawable to be the background of the LazyColumn. The background must fit the height and the width of the LazyColumn

I thought a possibility is to do it using a Box, placing a Image with the Drawable inside the Box, and over it, the LazyColumn, but the drawable must be the exact size of the LazyColumn, and I don't know how to do that.

Any ideas about how to achieve this will be appreciated.


Solution

  • You could use drawBehind modifier which provides access to the the underlying Canvas with DrawScope.drawIntoCanvas. It's important to also add clipToBounds to avoid drawing outside of the element.

    .clipToBounds()
    .drawBehind {
        drawIntoCanvas { canvas ->
           drawable.bounds = canvas.nativeCanvas.clipBounds
           drawable.draw(canvas.nativeCanvas)
        }
    }
    

    screen grab

    Full example:

    @Composable
    fun DrawableBackground() {
        val drawable = object : Drawable() {
            val paint: Paint = Paint().apply { setARGB(255, 0, 255, 0) }
    
            override fun draw(canvas: Canvas) {
                val top = bounds.top.toFloat()
                val bottom = bounds.bottom.toFloat()
                val left = bounds.left.toFloat()
                val right = bounds.right.toFloat()
                canvas.drawLine(right, top, left, bottom, paint)
                canvas.drawLine(left, top, right, bottom, paint)
            }
    
            override fun setAlpha(alpha: Int) {}
            override fun setColorFilter(colorFilter: ColorFilter?) {}
            override fun getOpacity(): Int = PixelFormat.OPAQUE
        }
    
        Column {
            var items by remember { mutableIntStateOf(5) }
            Row {
                Button(onClick = { ++items }) { Text("+") }
                Button(onClick = { --items }) { Text("-") }
            }
            LazyColumn(modifier = Modifier
                .fillMaxWidth()
                .clipToBounds()
                .drawBehind {
                    drawIntoCanvas { canvas ->
                        drawable.bounds = canvas.nativeCanvas.clipBounds
                        drawable.draw(canvas.nativeCanvas)
                    }
                }
            ) {
                items(items) { Text("Item $it") }
            }
        }
    }