Introducing Loupe: 10 minutes to implement Twitter-like image viewer

CATEGORY: Android, Kotlin

3 months ago, my boss requested me to implement a Twitter-like image viewer in our app. It supports pinch-to-zoom and swipe-to-dismiss gesture. Let’s see how the twitter’s image viewer works.

Twitter’s image viewer

Twitter's image viewer(Android)

Android’s specification

  • supports scrolling when zoomed in
  • supports over scaling
  • supports swipe-to-dismiss gesture with shared elements transition when zoomed out
  • supports horizontal paging

Twitter's image viewer(iOS)

iOS’s specification

  • supports scrolling & flinging when zoomed in
  • supports over scrolling & scaling
  • supports swipe-to-dismiss gesture with vertical translate animation when zoomed out
  • supports horizontal paging

Super cool…How can I implement this? 🤔

Any libraries?

There are many libraries for image zooming.

Although these great libraries provide pinch-to-zoom gesture, does not provide swipe-to-dismiss gesture(for now) 😫

How about using Behavior with existing libraries?

First, I have tried to use CoordinatorLayout.Behavior with existing libraries.

I wrote the below code.

VerticalSwipeDismissBehavior.kt

It seems to work with normal ImageView.

work with normal ImageView

But, in the case of PhotoView, behavior does not work 😿

does not work with PhotoView

Looks like Behavior’s touch event handling is conflicting with PhotoView’s 🤔

This method block was suspicious, but I didn’t realize how to fix this issue . And I tried the other libraries, but the results were similar 😵 I thought I need to handle the whole TouchEvent of the ImageView by myself.

After two months of work in my private time…finally, I released a new library!

Loupe

Loupe is an ImageView Helper for Android that supports pinch-to-zoom and swipe-to-dismiss gesture.

  • supports scrolling & flinging when zoomed in
  • supports over scrolling & scaling
  • supports two type swipe-to-dismiss gesture(shared elements transition & vertical translate animation)
  • supports horizontal paging
  • written in Kotlin
  • just a helper class of ImageView. So you can attach it to any ImageView you want. And working perfect with any image loader libraries.

loupe-1 loupe-2 loupe-3

How to use?

Create Loupe instance with your ImageView and implement the onViewTranslateListener. Code sample in Activity is something like this. (Loupe also works in Fragments)

val loupe = Loupe(imageView, container).apply { // imageView is your full screen ImageView and container is the direct parent of the ImageView

  onViewTranslateListener = object : Loupe.OnViewTranslateListener {

    override fun onStart(view: ImageView) {  
        
    }

    override fun onViewTranslate(view: ImageView, amount: Float) {  
        
    }

    override fun onRestore(view: ImageView) {  
        
    }

    override fun onDismiss(view: ImageView) {  
      finish()  
    }  
  }  
}

That’s all. See? It’s easy 😆

For more details, check the repository out 👀

https://github.com/igreenwood/loupe