In an Android photo viewing app, I want to allow users to:
- Zoom into a photo, drag to see its details, unzoom.
- Swipe to go to the next photo.
Implementation attempt using ZoomableDraweeView in Facebook's Fresco library:
private fun init(imageUri: Uri?) {
val hierarchy = GenericDraweeHierarchyBuilder.newInstance(resources)
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.setProgressBarImage(ProgressBarDrawable())
.setProgressBarImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.build()
zoomableDraweeView!!.hierarchy = hierarchy
zoomableDraweeView!!.setAllowTouchInterceptionWhileZoomed(false)
zoomableDraweeView!!.setIsLongpressEnabled(false)
zoomableDraweeView!!.setTapListener(DoubleTapGestureListener(zoomableDraweeView))
val controller: DraweeController = Fresco.newDraweeControllerBuilder()
.setUri(imageUri)
.setControllerListener(loadingListener)
.build()
zoomableDraweeView!!.controller = controller
Problem: When I zoom in, lift the fingers, then try to unzoom, this gets misinterpreted as a swipe and I am randomly sent to the next picture.
What am I doing wrong? How to disable swipes when zoomed in (or any better UX solution)?
- I specifically call
setAllowTouchInterceptionWhileZoomed(false)
, whose javadoc says: "If this is set to true, parent views can intercept touch events while the view is zoomed. For example, this can be used to swipe between images in a view pager while zoomed." - I tried to execute the swipe action only when
zoomableDraweeView.getZoomableController().isIdentity()
is false, but that does not always prevent unintended swipe. In particular, when I fully zoom out, often swipe accidentally happens, maybe becauseisIdentity()
has been updated by the time I release all fingers.getScaleFactor()
has the same issue. Another issue is that this solution only allows me to drag the zoomed picture with two fingers, dragging with one finger has no effect. - I thought about writing my own DraweeController and surface the zoom level (and ignore swipes when zoomed) but the base classes do not seem to contain any zoom level information.
By the way, here is how I detect swipes:
open class OnSwipeTouchListener(context: Context?) : View.OnTouchListener {
private inner class GestureListener :
GestureDetector.SimpleOnGestureListener() {
override fun onFling(
event1: MotionEvent,
event2: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
try {
val diffX: Float = event2.x - event1.x
if (abs(diffX) > abs(diffY)) {
if (abs(diffX) > SWIPE_THRESHOLD && abs(velocityX) >
SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
goToTheNextPhoto() // Swipe detected.