I have an offset value that is calculated or reset as
var offset by remember(key1 = contentScale, key2 = imageBitmap) {
mutableStateOf(Offset.Unspecified)
}
This is basically a color detector from an Image
but when ContentScale
of the custom Image
I wrote or ImageBitmap
changes I want to reset it to Offset.Unspecified
so it doesn't draw markers outside of area that is image being drawn, the grey area in gif.
This is simplified but reproducible code, I
use Jetpack Compose 1.2.0-beta01
@Composable
fun ImageColorDetector(
modifier: Modifier = Modifier,
imageBitmap: ImageBitmap,
contentScale: ContentScale = ContentScale.FillBounds,
onColorChange: (ColorData) -> Unit
) {
var offset by remember(key1 = contentScale, key2 = imageBitmap) {
mutableStateOf(Offset.Unspecified)
}
println(
"✊ImageColorDetector() imageBitmap: $imageBitmap\n" +
"bitmap: ${imageBitmap.asAndroidBitmap()}\n" +
"width: ${imageBitmap.width}, height: ${imageBitmap.height}\n" +
"offset: $offset\n" +
"contentScale: $contentScale\n\n"
)
Box(
modifier = modifier
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
offset = change.position
println("onTouchEvent: offset: $offset")
}
}
) {
Image(
bitmap = imageBitmap,
contentScale = contentScale,
contentDescription = null
)
}
Text("Offset: $offset")
}
In detectDragGestures
I see that offset is updated on drag gesture and when ImageBitmap
or ContentScale
changes, I saw in parent and this composable that they are not the same instances, so remember
should be recalculate with new keys but it doesn't seem to work.
I/System.out: ⛺️ ImageColorDetectionDemo imageBitmap: androidx.compose.ui.graphics.AndroidImageBitmap@5552c68
I/System.out: bitmap: android.graphics.Bitmap@93bc881
I/System.out: width: 236, height: 394
I/System.out: contentScale: androidx.compose.ui.layout.ContentScale$Companion$Crop$1@3226649
I/System.out:
I/System.out: ✊ImageColorDetector() imageBitmap: androidx.compose.ui.graphics.AndroidImageBitmap@5552c68
I/System.out: bitmap: android.graphics.Bitmap@93bc881
I/System.out: width: 236, height: 394
I/System.out: offset: Offset(0.0, 0.0)
I/System.out: contentScale: androidx.compose.ui.layout.ContentScale$Companion$Crop$1@3226649
I/System.out:
I/System.out: ⛺️ ImageColorDetectionDemo imageBitmap: androidx.compose.ui.graphics.AndroidImageBitmap@7607f98
I/System.out: bitmap: android.graphics.Bitmap@286d3f1
I/System.out: width: 736, height: 920
I/System.out: contentScale: androidx.compose.ui.layout.ContentScale$Companion$Crop$1@3226649
I/System.out:
I/System.out: ✊ImageColorDetector() imageBitmap: androidx.compose.ui.graphics.AndroidImageBitmap@7607f98
I/System.out: bitmap: android.graphics.Bitmap@286d3f1
I/System.out: width: 736, height: 920
I/System.out: offset: Offset(0.0, 0.0)
I/System.out: contentScale: androidx.compose.ui.layout.ContentScale$Companion$Crop$1@3226649
ContentScale
is from default image code; each is an Object
, so changing from Crop
to Fit
means a key
is set.
I changed
modifier
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
offset = change.position
println("onTouchEvent: offset: $offset")
}
}
to
modifier
.pointerInput(contentScale, imageBitmap) {
detectDragGestures { change, dragAmount ->
offset = change.position
println("onTouchEvent: offset: $offset")
}
}
When a [pointerInput] modifier is created by composition, if [block] captures any local variables to operate on, two patterns are common for working with changes to those variables depending on the desired behavior.
Specifying the captured value as a [key][key1] parameter will cause [block] to cancel and restart from the beginning if the value changes:
Modifier.pointerInput holds to previous MutableState
instance while new instance of MutableState
is created when any remember keys change and Modifier.pointerInput has no way accessing. It still hold previous instance and gesture loop runs with old MutableState with no updates.Restarting pointerInput with keys makes sure of the latest MutableState
is read.