Search code examples
androidandroid-jetpack-composeandroid-glidemaximize-window

How to maximize image on button click in jetpack compose?


I have a GlideImage that is inside a Box. Inside that Box, there is also a button with an icon. I want that, when I click on the button, the image is maximized and occupies the whole screen with a button in the lower right corner where it is possible to minimize it. I would also like to zoom in on it. Does anyone know how I can do this and if it's possible in the current state of Jetpack Compose?

I leave you the code I have to generate the Box, with the image and the icon.

Thanks in advance for any help.

@ExperimentalGlideComposeApi
@Composable
fun BuildImage(imageUrl: String) {
    Box(
        modifier = Modifier
            .padding(vertical = 25.dp, horizontal = 25.dp)
            .background(
                brush = Brush.linearGradient(
                    listOf(
                        Color.Gray,
                        Color.White
                    )
                ),
                shape = RoundedCornerShape(14.dp)
            )
            .clip(RoundedCornerShape(14.dp))
    ) {
        GlideImage(
            model = imageUrl,
            contentDescription = null,
            contentScale = ContentScale.FillBounds
        )

        Box(modifier = Modifier.matchParentSize(), contentAlignment = Alignment.BottomEnd) {
            IconButton(
                onClick = { /* TO IMPLEMENT */ },
                modifier = Modifier
                    .padding(11.dp)
                    .background(Color.Blue, RoundedCornerShape(3.dp))
                    .clip(RoundedCornerShape(3.dp))
                    .size(52.dp)
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.maximize),
                    contentDescription = null,
                    tint = Color.Unspecified
                )
            }
        }
    }
}

Solution

  • For my use case, I used the suggestion of @ADM to solve my problem. When I clicked on the button, a dialog opened that took up the entire screen and inside it showed the image I needed using Glide. To Zoom the image, I used the ZoomableImage method that you can see below.

    Dialog(
        properties = DialogProperties(usePlatformDefaultWidth = false),
        onDismissRequest = { /* implement */ }
    ) {
        Box(modifier = Modifier.fillMaxSize()) {
          ZoomableImage(imageUrl)
        }
    }
    
    @ExperimentalGlideComposeApi
    @Composable
    fun ZoomableImage(model: Any, contentDescription: String? = null) {
        val angle by remember { mutableStateOf(0f) }
        var zoom by remember { mutableStateOf(1f) }
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }
    
        val configuration = LocalConfiguration.current
        val screenWidth = configuration.screenWidthDp.dp.value
        val screenHeight = configuration.screenHeightDp.dp.value
    
        GlideImage(
            model,
            contentDescription = contentDescription,
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .graphicsLayer(
                    scaleX = zoom,
                    scaleY = zoom,
                    rotationZ = angle
                )
                .pointerInput(Unit) {
                    detectTransformGestures(
                        onGesture = { _, pan, gestureZoom, _ ->
                            zoom = (zoom * gestureZoom).coerceIn(1F..4F)
                            if (zoom > 1) {
                                val x = (pan.x * zoom)
                                val y = (pan.y * zoom)
                                val angleRad = angle * PI / 180.0
    
                                offsetX =
                                    (offsetX + (x * cos(angleRad) - y * sin(angleRad)).toFloat()).coerceIn(
                                        -(screenWidth * zoom)..(screenWidth * zoom)
                                    )
                                offsetY =
                                    (offsetY + (x * sin(angleRad) + y * cos(angleRad)).toFloat()).coerceIn(
                                        -(screenHeight * zoom)..(screenHeight * zoom)
                                    )
                            } else {
                                offsetX = 0F
                                offsetY = 0F
                            }
                        }
                    )
                }
                .fillMaxSize()
        )
    }