I have this square image component with rounded corners that I want to overlay a solid color over on hover:
@Composable
fun MyImage(imageUri: String) {
var likeOverlayColor = animateColorAsState(targetValue = Color(0, 0, 0, 100))
val imageShape = RoundedCornerShape((WindowSize.windowHeight / 10).dp)
val imageAspectRatio = 1f
Box {
Image(
painter = painterResource(imageUri),
contentDescription = null,
contentScale = ContentScale.Crop,
alignment = Alignment.TopStart,
modifier = Modifier
.fillMaxHeight()
.aspectRatio(imageAspectRatio)
.clip(imageShape)
.align(Alignment.CenterStart)
)
}
}
How would I now overlay a solid color (rgb: 0, 0, 0, 100) over it on hover?
I have tried to use
var imageOverlayColor = remember { mutableStateOf(Color(0, 0, 0, 0)) }
Box (
Modifier.onPointerEvent(
eventType = PointerEventType.Enter,
pass = PointerEventPass.Main,
onEvent = {
imageOverlayColor = animateColorAsState(targetValue = Color(0, 0, 0, 100))
}
)
) {
Image (...) {
}
Surface (
modifier = Modifier
.fillMaxHeight()
.aspectRatio(imageAspectRatio)
.clip(imageShape)
.align(Alignment.CenterStart)
) {}
}
but got this error: @Composable invocations can only happen from the context of a @Composable function
The problem is here that you are calling the @Composable
function animateColorAsState
inside the onEvent handler context, which is not a composable function.
To use animateColorAsState
correctly, you should set your color outside of the event handler.
Use for example a variable showOverlay
to save the state of the overlay. Then you can specify different colors for your imageOverlayColor
.
See the example code:
@Composable
fun MyImage(imageUri: String) {
val imageShape = RoundedCornerShape((WindowSize.windowHeight / 10).dp)
val imageAspectRatio = 1f
// boolean variable for overlay visibility
var showOverlay by remember { mutableStateOf(false) }
// Specify different color depending on showOverlay value
val imageOverlayColor = animateColorAsState(if (showOverlay) Color(0, 0, 0, 0) else Color(0, 0, 0, 100))
Box (
Modifier.onPointerEvent(
eventType = PointerEventType.Enter,
pass = PointerEventPass.Main,
onEvent = {
// toggle overlay visibility
showOverlay = !showOverlay
}
)
) {
Image (...) {
}
Surface (
modifier = Modifier
.fillMaxHeight()
.aspectRatio(imageAspectRatio)
.clip(imageShape)
.align(Alignment.CenterStart)
) {}
}
}
And if you just want to change the opacity of the element, consider using just a value overlayOpacity
and use animateFloatAsState
.