I am currently playing with my old Instant Lab device and I am trying to recreate parts of the old app in jetpack compose.
A feature of the device is to detect 3 touch points on the screen in order to create the border of the image to display.
I was able to dectect the 3 touche points using jetpack compose and find the coordinate (x, y) of each touch points :
Now I would like to display my image between these touch points. I know that I need to use the Image
Composable in order to display. But I do not know how to apply the right transformation in order to display this composable between these 3 points using rotation and absolute position (?).
Expected result:
Thank you in advance for your help.
Edit:
I tried using a custom shape I apply to a surface with the following composable :
@Composable
private fun Exposing(pointersCoordinates: PointersCoordinates)
{
val exposureShape = GenericShape { _, _ ->
moveTo(pointersCoordinates.xTopLeft(), pointersCoordinates.yTopLeft())
lineTo(pointersCoordinates.xTopRight(), pointersCoordinates.yTopRight())
lineTo(pointersCoordinates.xBottomRight(), pointersCoordinates.yBottomRight())
lineTo(pointersCoordinates.xBottomLeft(), pointersCoordinates.yBottomLeft())
}
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black)
) {
Surface(
modifier = Modifier.fillMaxSize(),
shape = exposureShape,
color = Color.Yellow,
border = BorderStroke(1.dp, Color.Red)
) {
Image(
modifier = Modifier.fillMaxSize(),
bitmap = viewModel?.bitmap?.asImageBitmap() ?: ImageBitmap(0, 0),
contentDescription = "photo"
)
}
}
}
It's working correctly :) But is it the best way to do it?
Since you are able to get a Rect from touch points you can use Canvas or Modifier.drawWithContent{}.
How to clip or cut a Composable?
Another approach for clipping is using clip() function of DrawScope, this approach only clips to a Rect.
Also you can use Modifier.clip() with custom shape to clip it as required as in this answer
If you don't want to clip your image draw whole image insider rect you can do it with dstOffset
with dstSize
or translate
with dstSize
@Composable
private fun DrawImageWithTouchSample() {
val rect = Rect(topLeft = Offset(100f, 100f), bottomRight = Offset(1000f, 1000f))
val modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures {
// Tap here to get points
}
}
val image = ImageBitmap.imageResource(id = R.drawable.landscape5)
Canvas(modifier = modifier) {
// Clip image
clipRect(
left = rect.left,
top = rect.top,
right = rect.right,
bottom = rect.bottom
){
drawImage(image = image)
}
// Not clipping image
// drawImage(
// image = image,
// dstOffset = IntOffset(x = rect.left.toInt(), y = rect.top.toInt()),
// dstSize = IntSize(width = rect.width.toInt(), height = rect.height.toInt())
// )
//
translate(
left = rect.left,
top = rect.top + 1000
){
drawImage(
image = image,
dstSize = IntSize(width = rect.width.toInt(), height = rect.height.toInt())
)
}
}
}
Image on top is clipped with clipRect
while second one is scaled to fit inside rect because of dstSize