I have a TransformableState that is used for zoomi...
# compose
j
I have a TransformableState that is used for zooming and moving an image around freely. How would I optimally measure the image location so it does not get moved outside of the window and change the pan/offsets of the transformableState so this does not happen. I have the Modifier.onGloballyPositioned which gives me the LayoutCoordinates. How can I get the Window size to calculate by how much i need to change the offsets (or are there better approaches?)
^ This should not happen
a
onGloballyPositioned tells you that something has been positioned at a particular location at a point where it's too late for you to change the outcome of that positioning. It sounds like you want to restrict the positioning as it's being determined instead, which your TransformableState should already know as it's performing its work.
j
Where would I tell it? Similarly to how I coerce the scale? In that case, where would I measure how wide the screen is?
Copy code
@Composable
fun BoxScope.StaticImage(url: String) {
    var scale by remember { mutableStateOf(1f) }
    var offset by remember { mutableStateOf(Offset.Zero) }
    val transformableState = rememberTransformableState { zoomChange, panChange, _ ->
        scale = (scale * zoomChange).coerceIn(1f, 10f)
        offset += panChange
    }
    val scope = rememberCoroutineScope()


    GlideImage(
        url,
        null,
        Modifier
            .scale(scale)
            .offset {
                IntOffset(offset.x.roundToInt(), offset.y.roundToInt())
            }
            .pointerInput(Unit) {
                detectTapGestures(onDoubleTap = {
                    scope.launch { transformableState.animateZoomBy(3f) }
                })
            }
            .pointerInput(Unit) {
                detectDragGestures { _, dragAmount ->
                    offset += dragAmount
                }
            }
            .transformable(transformableState),
        fadeIn = true,
        loading = {
            CircularProgressIndicator()
        }
    )
    DownloadButton(...)
}
a
you can use
.onSizeChanged {}
to determine the size of an element, and use that recorded size to constrain positioning
as you start combining a bunch of modifiers to do this though, you might find it easier to use one
Modifier.layout {}
to do the sizing and positioning in one place instead
t
I've written a Zoomable Composable which does exactly the same behavior and hope it can help https://github.com/TwidereProject/TwidereX-Android/blob/develop/app/src/main/kotlin/com/twidere/twiderex/component/foundation/Zoomable.kt
t
Hey @Tlaster, the link is broken, do you still have it?
t
@Tornike Kikalishvili I've made a package for it https://github.com/Tlaster/Zoomable
👍 1
t
Thanks a lot @Tlaster