'Jetpack Compose androidx.compose.ui.graphics.Canvas not refreshing correctly for clipping Bitmap
With androidx.compose.foundation.Canvas, default Canvas for Jetpack Compose
@Composable
fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) =
Spacer(modifier.drawBehind(onDraw
correctly refreshes drawing on Canvas when mutableState Offset changes
var offset by remember {
mutableStateOf(Offset(bitmapWidth / 2f, bitmapHeight / 2f))
}
Canvas(modifier = canvasModifier.fillMaxSize()) {
val canvasWidth = size.width.roundToInt()
val canvasHeight = size.height.roundToInt()
drawImage(
image = dstBitmap,
srcSize = IntSize(dstBitmap.width, dstBitmap.height),
dstSize = IntSize(canvasWidth, canvasHeight)
)
drawCircle(
center = offset,
color = Color.Red,
radius = canvasHeight.coerceAtMost(canvasWidth) / 8f,
)
}
With androidx.compose.ui.graphics.Canvas, i add full implementation to test this out easily and much appreciated if you come up with a solution.
@Composable
fun NativeCanvasSample2(imageBitmap: ImageBitmap, modifier: Modifier) {
BoxWithConstraints(modifier) {
val imageWidth = constraints.maxWidth
val imageHeight = constraints.maxHeight
val bitmapWidth = imageBitmap.width
val bitmapHeight = imageBitmap.height
var offset by remember {
mutableStateOf(Offset(bitmapWidth / 2f, bitmapHeight / 2f))
}
val canvasModifier = Modifier.pointerMotionEvents(
Unit,
onDown = {
val position = it.position
val offsetX = position.x * bitmapWidth / imageWidth
val offsetY = position.y * bitmapHeight / imageHeight
offset = Offset(offsetX, offsetY)
it.consumeDownChange()
},
onMove = {
val position = it.position
val offsetX = position.x * bitmapWidth / imageWidth
val offsetY = position.y * bitmapHeight / imageHeight
offset = Offset(offsetX, offsetY)
it.consumePositionChange()
},
delayAfterDownInMillis = 20
)
val canvas: androidx.compose.ui.graphics.Canvas = Canvas(imageBitmap)
val paint1 = remember {
Paint().apply {
color = Color.Red
}
}
canvas.apply {
val nativeCanvas = this.nativeCanvas
val canvasWidth = nativeCanvas.width.toFloat()
val canvasHeight = nativeCanvas.height.toFloat()
drawCircle(
center = offset,
radius = canvasHeight.coerceAtMost(canvasWidth) / 8,
paint = paint1
)
}
Image(
modifier = canvasModifier,
bitmap = imageBitmap,
contentDescription = null,
contentScale = ContentScale.FillBounds
)
Text(
"Offset: $offset",
modifier = Modifier.align(Alignment.BottomEnd),
color = Color.White,
fontSize = 16.sp
)
}
}
First issue it never refreshes Canvas without Text or something else reading Offset.
Second issue is as in the image below. It doesn't clear previous drawing on Image, i tried every possible solution in this question thread but none of them worked.
I tried drawing image with BlendMode, drawColor(Color.TRANSPARENT,Mode.Multiply) with native canvas and many combinations still not able to have the same result with Jetpack Compose Canvas.
val erasePaint = remember {
Paint().apply {
color = Color.Transparent
blendMode = BlendMode.Clear
}
}
with(canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
drawImage(imageBitmap, topLeftOffset = Offset.Zero, erasePaint)
drawCircle(
center = offset,
radius = canvasHeight.coerceAtMost(canvasWidth) / 8,
paint = paint1
)
restoreToCount(checkPoint)
}
I need to use androidx.compose.ui.graphics.Canvas as you can see operations on Canvas are reflected to Bitmap and using this i'm planning to create foundation for cropping Bitmap
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|


