Question

I've implemented a gallery using ImageViewTouch: https://github.com/sephiroth74/ImageViewZoom. This enables to zoom using DoupleTap and other nice stuff, which works great.

These images are added in a PagerAdapter to enable swipe between images as well.

However, I'm currently having issues with scrolling in x-axis when image is zoomed in. I would like to disable the PageAdapters touch listener if the user has zoomed the image.

However I would like to turn it on again if there are no zoom OR if the image is zoomed in and is at the far end on the image.

GalleryActivity which extends FragmentActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gallery_layout);
    
    GalleryAdapter galleryAdapter = new GalleryAdapter(GalleryActivity.this, images);

    // create view pager using the fragment adapter
    final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
    viewPager.setAdapter(galleryAdapter);
    viewPager.setOnPageChangeListener(new PageChangeListener());
}

My Adapter

public class GalleryAdapter extends PagerAdapter {

Matrix imageMatrix;
private Activity activity;
private ArrayList<Bitmap> images;
private LayoutInflater inflater;

// constructor
public GalleryAdapter(Activity activity, ArrayList<Bitmap> images) {
    this.activity = activity;
    this.images = images;
}

@Override
public int getCount() {
    return this.images.size();
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view == ((RelativeLayout) object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    final ImageViewTouch imgDisplay;
    final Bitmap image;

    inflater = (LayoutInflater) activity
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View viewLayout = inflater.inflate(R.layout.gallery_image,
            container, false);

    imgDisplay = (ImageViewTouch) viewLayout.findViewById(R.id.image);
    imgDisplay.setDisplayType(DisplayType.FIT_IF_BIGGER);
    imgDisplay.setVisibility(View.GONE);
    image = images.get(position);

    imgDisplay.setDoubleTapEnabled(true);

    if (null == GalleryAdapter.this.imageMatrix) {
        GalleryAdapter.this.imageMatrix = new Matrix();
    } else {
        // get the current image matrix, if we want restore the
        // previous matrix once the bitmap is changed
        imageMatrix = imgDisplay.getDisplayMatrix();
    }

    imgDisplay.setImageBitmap(image, GalleryAdapter.this.imageMatrix
            .isIdentity() ? null : GalleryAdapter.this.imageMatrix,
            ImageViewTouchBase.ZOOM_INVALID,
            ImageViewTouchBase.ZOOM_INVALID);
    imgDisplay.setVisibility(View.VISIBLE);

    viewLayout.setTag(imgDisplay);

    ((ViewPager) container).addView(viewLayout);

    return viewLayout;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    ((ViewPager) container).removeView((RelativeLayout) object);
}

Is this something anybody has achieved?

Was it helpful?

Solution

You should extend the ImageViewZoom with your own ImageView subclass. Then try something like this:

this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (getScale() > 1f) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
}
});

This should basically disallow paging whenever the image is scaled/zoomed beyond 1x. Thus, the user must zoom out in order to page.

See here https://github.com/sephiroth74/ImageViewZoom/issues/38

OTHER TIPS

I have extended the image view touch and posted my code below. This code is much more similar to Android gallery: double tap always zooms out unless you are already zoomed out; if zoomed in, scrolling to next image will be disabled unless you are at edge of image. Hope someone finds this useful. (I extended the existing class and made modifications until it worked, it may not be the cleanest code :) )

public class ExtendedImageViewTouch extends ImageViewTouch {

static final float SCROLL_DELTA_THRESHOLD = 1.0f;

public ExtendedImageViewTouch(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public ExtendedImageViewTouch(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public ExtendedImageViewTouch(Context context) {
    super(context);
    init();
}

private void init() {
    OnTouchListener listener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (getScale() > 1f) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            return false;
        }
    };
    setOnTouchListener(listener);
    setDisplayType(DisplayType.FIT_TO_SCREEN);
}

@Override
protected float onDoubleTapPost(float scale, float maxZoom) {
    if (scale!=1f) {
        mDoubleTapDirection = 1;
        return 1f;
    }
    if (mDoubleTapDirection == 1) {
        mDoubleTapDirection = -1;
        if ( ( scale + ( mScaleFactor * 2 ) ) <= maxZoom ) {
            return scale + mScaleFactor;
        } else {
                mDoubleTapDirection = -1;
                return maxZoom;
        }
    } else {
        mDoubleTapDirection = 1;
        return 1f;
    }
}

@Override
public boolean canScroll( int direction ) {
        RectF bitmapRect = getBitmapRect();
        updateRect( bitmapRect, mScrollRect );
        Rect imageViewRect = new Rect();
        getGlobalVisibleRect( imageViewRect );

        if( null == bitmapRect ) {
                return false;
        }

        if ( Math.abs( bitmapRect.right - imageViewRect.right ) < SCROLL_DELTA_THRESHOLD ) {
                if ( direction < 0 ) {
                        return false;
                }
        }

        if (Math.abs( bitmapRect.left - mScrollRect.left ) < SCROLL_DELTA_THRESHOLD) {
            if ( direction > 0 ) {
                return false;
            }
        }
        return true;
}

@Override
public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX, float distanceY ) {
    if ( getScale() == 1f ) return false;
    if (distanceX!=0 && !canScroll((int) -distanceX)) {
        getParent().requestDisallowInterceptTouchEvent(false);
        return false;
    } else {
        getParent().requestDisallowInterceptTouchEvent(true);
        mUserScaled = true;
        scrollBy( -distanceX, -distanceY );
        invalidate();
        return true;
   }
}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top