Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep ZoomState and position if loading Images in same screen. #104

Open
jizhe7550 opened this issue Oct 14, 2024 · 8 comments
Open

Keep ZoomState and position if loading Images in same screen. #104

jizhe7550 opened this issue Oct 14, 2024 · 8 comments

Comments

@jizhe7550
Copy link

jizhe7550 commented Oct 14, 2024

Hello my situation that I have ImagePreview pager and I will show thumbnail first then Preview then fullSizeImage (3 different paths), which require 3 downloading process in same screen. I am wondering whether it is possible to support

  1. Once thumbnail loading success, then set it as placeholder. Then the screen won't see flashing 3 time dude to the 3 paths changes.
  2. Is it possible to keep the zoomState, then this can keep the position in same page after zooming?

Now my code like this

Box(
        modifier = modifier,
        contentAlignment = Alignment.Center,
    ) {
       // fullSizePath will change from thumbnailPath -> previewPath -> fullSizePath
        var imagePath by remember(fullSizePath) {
            mutableStateOf(fullSizePath)
        }

        val request = ImageRequest.Builder(LocalContext.current)
            .data(imagePath)
            .listener(
                onError = { _, _ ->
                    imagePath = errorImagePath
                }
            )
            .crossfade(300)
            .build()

        ZoomableAsyncImage(
            model = request,
            state = imageState,
            gesturesEnabled = enableZoom && !isMagnifierMode,
            contentDescription = "Image Preview",
            modifier = Modifier.fillMaxSize(),
            onClick = {
                onImageTap()
            },
            onDoubleClick = DoubleClickToZoomListener.cycle(maxZoomFactor = 3f),
        )
    }

I know it may be not easy, so could you please guide if I can custom this logic in somewhere? Thank you very much.

flash.and.position.move.mp4
@saket
Copy link
Owner

saket commented Oct 14, 2024

Is the overall goal here to retain the pan and zoom state across image changes? If so, I'd definitely like to support it but it has proven to be non-trivial in my past attempts.

For your thumbnails, have you tried using coil's placeholder for displaying them? Telephoto will smoothly swap out placeholders when their full quality versions are ready and even block zoom events until then. https://saket.github.io/telephoto/zoomableimage/#placeholders

For smoothly transitioning from a preview image to its full-sized image, is the image resolution known before hand for the full-sized variant?

@jizhe7550
Copy link
Author

Hi saket, thanks for you reply.

Is the overall goal here to retain the pan and zoom state across image changes? If so, I'd definitely like to support it but it has proven to be non-trivial in my past attempts.

In my use case, it is essential to provide good UX. We don't want to reset the current zoom state as soon the fullSize downloaded. If you see my video, each quality transition: thumbnail -> preview -> fullSize, the central position is changing. I guess it is caused by the different size of picture (thumbnail/preview/fullsize). But I have no idea to handle it.

For your thumbnails, have you tried using coil's placeholder for displaying them? Telephoto will smoothly swap out placeholders when their full quality versions are ready and even block zoom events until then.

Great to know!
But does the placeholder support static resource only? In our case, the thumbnail is dynamic which downloaded from some API first.

For smoothly transitioning from a preview image to its full-sized image, is the image resolution known before hand for the full-sized variant?

Unfortunately, we don't know.

Again, thank you so much.

@ErickSumargo
Copy link

Yeah it'd be great @saket if Telephoto can support it.
I also got some reviews from my users they sometimes feel annoyed the zoom is reset when higher quality arrives.

@saket
Copy link
Owner

saket commented Oct 16, 2024

But does the placeholder support static resource only? In our case, the thumbnail is dynamic which downloaded from some API first.

Gotcha. Yea I wish Coil had support for dynamic thumbnails.

Unfortunately, we don't know.

Noted. In theory it should be possible to retain the zoom and offset values if the new image shares the same aspect ratio as the old one. I'll try working on this soon.

@jizhe7550
Copy link
Author

Thank you very much.

@jizhe7550
Copy link
Author

Hi Saket, any progress on this?

@saket
Copy link
Owner

saket commented Nov 18, 2024

I unfortunately haven't been able to find time to work on this yet. I made some progress in the last release by adapting zoom & pan values to a new viewport size:

/**
* Used when [ZoomableState]'s saved gesture state cannot be restored due to viewport size changes.
* Adjusts zoom and pan values to maintain the content's centroid position in the new viewport.
*/
internal class GestureStateAdjuster(
private val oldFinalZoom: ScaleFactor,
private val oldContentOffsetAtViewportCenter: Offset, // Present in the content's coordinate space.
) {
fun adjustForNewViewportSize(

I think we can write something similar for adapting to new content sizes. Wanna help me out?

@jizhe7550
Copy link
Author

Hello, my job has changed and I am unable to support the work. I will notify my colleagues for follow-up. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants