https://kotlinlang.org logo
#compose
Title
# compose
k

Klaas Kabini

03/07/2020, 7:32 AM
Is this a bug or not. The Box does not produce a circular shape if you do this
Copy code
Box(modifier = modifier + ImagePainter(image = image).toModifier(),
            shape = CircleShape,
            border = Border(borderWidth, borderColor))
k

Klaas Kabini

03/07/2020, 7:59 AM
@Vinay Gaba check the implementation of SimpleImage. it provides the direction of how to achieve what we needed
@Vinay Gaba the only way to make the box clip is to either wrap it in side a Surface or add a ClipModifier as follows
Copy code
val imageModifier = ImagePainter(image).toModifier(
        scaleFit = ScaleFit.FillMaxDimension,
        colorFilter = tintColor?.let { ColorFilter(it, BlendMode.srcIn) }
    )

Box(modifier = modifier + ClipModifier + imageModifier,
    shape = shape)
Copy code
private object ClipModifier : DrawModifier {
    override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
        canvas.save()
        val radius = Radius.circular((min(size.width, size.height)/2).value)
        canvas.clipRRect(RRect(size.toRect(), radius))
        drawContent()
        canvas.restore()
    }
}
@Vinay Gaba in case you are interested I implemented a flexible way to have an image view clipped to any shape type you want.
Copy code
@Composable
fun Image(modifier: Modifier = Modifier.None,
          image: Image,
          shape: Shape,
          tintColor: Color? = null,
          borderColor: Color = Color.Transparent,
          borderWidth: Dp = 0.dp) {

    val imageModifier = ImagePainter(image).toModifier(
        scaleFit = ScaleFit.FillMaxDimension,
        colorFilter = tintColor?.let { ColorFilter(it, BlendMode.srcIn) }
    )

    val clipModifier = when (shape) {
        is RoundedCornerShape -> RoundedCornerClipModifier(shape.topLeft, shape.topRight, shape.bottomLeft, shape.bottomRight)
        else -> RectangleClipModifier
    }

    Box(modifier = modifier + clipModifier + imageModifier,
        shape = shape,
        border = Border(borderWidth, borderColor))

}

private object RectangleClipModifier : DrawModifier {
    override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
        canvas.save()
        canvas.clipRect(size.toRect())
        drawContent()
        canvas.restore()
    }
}

private data class RoundedCornerClipModifier(val topLeftCornerSize: CornerSize,
                                             val topRightCornerSize: CornerSize,
                                             val bottomLeftCornerSize: CornerSize,
                                             val bottomRightCornerSize:CornerSize) : DrawModifier {
    override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
        canvas.save()
        val topLeft =  topLeftCornerSize.toPx(size, density)
        val topRight =  topRightCornerSize.toPx(size, density)
        val bottomLeft =  bottomLeftCornerSize.toPx(size, density)
        val bottomRight =  bottomRightCornerSize.toPx(size, density)

        canvas.clipRRect(RRect(rect = size.toRect(),
            topLeft = topLeft.toRadius(),
            topRight = topRight.toRadius(),
            bottomLeft = bottomLeft.toRadius(),
            bottomRight = bottomRight.toRadius()))
        drawContent()
        canvas.restore()
    }
}

private fun Px.toRadius() = Radius.circular(this.value)
💯 1
v

Vinay Gaba

03/07/2020, 6:29 PM
what I just learned is that the order of the modifier has an impact on the results!
k

Klaas Kabini

03/07/2020, 6:42 PM
I agree
v

Vinay Gaba

03/07/2020, 10:10 PM
@Klaas Kabini I just tried your
RoundedCornerClipModifier
but unfortunately it’s not clipping the image. I think your code looks correct though!
I think I see what’s going on - it works only if the scaleType is set to occupy the
FILL_WIDTH
if the box width is not specified.
moreover, it requires width & height to be specified for the clipping to work correctly without the scaleType.