View Pager + ImageView +Pinch Zoom + Rotation

47,662

Solution 1

EDIT 2: Example code has been pushed to the master branch of TouchImageView. Here is a link to the example activity and a link to the ExtendedViewPager.


EDIT: added code adapting the example link to TouchImageView. Note: you will need the latest code, which is currently in the dev branch. In the future, this will be included in v1.2.0. You know you have the latest code if TouchImageView overrides canScrollHorizontally.

Step 1: Extend ViewPager and override canScroll to call canScrollHorizontallyFroyo.

public class ExtendedViewPager extends ViewPager {

public ExtendedViewPager(Context context) {
    super(context);
}

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

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if (v instanceof TouchImageView) {
        return ((TouchImageView) v).canScrollHorizontallyFroyo(-dx);
    } else {
        return super.canScroll(v, checkV, dx, x, y);
    }
}

}

Step 2: Modify TouchImageView by adding canScrollHorizontallyFroyo:

public boolean canScrollHorizontallyFroyo(int direction) {
    return canScrollHorizontally(direction);
}

Step 3: Your activity

public class TouchImageViewActivity extends Activity {

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ExtendedViewPager mViewPager = (ExtendedViewPager) findViewById(R.id.view_pager);
        setContentView(mViewPager);
        mViewPager.setAdapter(new TouchImageAdapter());
    }

    static class TouchImageAdapter extends PagerAdapter {

            private static int[] images = { R.drawable.img1, R.drawable.img2, R.drawable.img3 };

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

            @Override
            public View instantiateItem(ViewGroup container, int position) {
                    TouchImageView img = new TouchImageView(container.getContext());
                    img.setImageResource(images[position]);
                    container.addView(img, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
                    return img;
            }

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

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

    }
}

Step 4: main.xml

<com.example.touch.ExtendedViewPager 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

TouchImageView is actually my project. I currently have a fix in the dev branch for integration with ViewPagers, which will be pushed to master in an upcoming release. Unfortunately, this fix is only applicable for API 14 and greater since honeycomb and earlier do not call canScrollHorizontally. If you need to support older APIs, then you will need to implement a workaround in your ViewPager. Here is an example.

Solution 2

I found pretty solution with ImageViewZoom library. In order to scroll zoomed image in ViewPager I created own ViewPager:

public class ExtendedViewPager extends ViewPager {

    public ExtendedViewPager(Context context) {
        super(context);
    }

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

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if (v instanceof ImageViewTouch) {
            return ((ImageViewTouch) v).canScroll(dx);
        } else {
            return super.canScroll(v, checkV, dx, x, y);
        }
    }
}

See more https://gist.github.com/atermenji/3781644

Solution 3

After several hours of testing the solutions above I have finally found the awesome Subsampling Scale Image View library, which works even with standard ViewPager from Android Support Package.

Solution 4

My solution using ImageViewZoom Library is based on this custom ViewPager:

public class ImageViewTouchViewPager extends ViewPager {

    public ImageViewTouchViewPager(Context context) {
        super(context);
    }

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

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if (v instanceof ImageViewTouch) {
            ImageViewTouch imageViewTouch = (ImageViewTouch)v;
            if (imageViewTouch.getScale() == imageViewTouch.getMinScale()) {
                return super.canScroll(v, checkV, dx, x, y);
            }
            return imageViewTouchCanScroll(imageViewTouch, dx);
        } else {
            return super.canScroll(v, checkV, dx, x, y);
        }
    }


    /**
     * Determines whether the ImageViewTouch can be scrolled.
     *
     * @param direction - positive direction value means scroll from right to left,
     *                  negative value means scroll from left to right
     * @return true if there is some more place to scroll, false - otherwise.
     */
    private boolean imageViewTouchCanScroll(ImageViewTouch v, int direction){
        RectF bitmapRect = v.getBitmapRect();
        Rect imageViewRect = new Rect();
        getGlobalVisibleRect(imageViewRect);

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

        if (direction < 0) {
            return Math.abs(bitmapRect.right - imageViewRect.right) > 1.0f;
        }else {
            return Math.abs(bitmapRect.left - imageViewRect.left) > 1.0f;
        }

    }
}
Share:
47,662

Related videos on Youtube

Avtar Guleria
Author by

Avtar Guleria

Android Developer Total Exp: 7 Years Area: Mobile Applications Skill: Android, iOS, Cocos2D, LibGDX LinkedIn Profile: Avtar Guleria

Updated on January 06, 2022

Comments

  • Avtar Guleria
    Avtar Guleria over 2 years

    I want to implement Pinch Zoom on Imageview, with in View Pager similar to Default Android Gallery. I have found multiple source over GitHub, But the zoom and sliding just work for only first image.

    What I have tried:

    1.) TouchImageView

    2.) PhotoView

    3.) Android Touch Gallery

    All the above links works fine for single image view. But when it comes to Images in View pager, They have some glitches and only works fine for first image in the View Pager. When we scroll over to 3rd 4th image in view pager, Dragging functionality not working as expected if the image is zoomed.

    Please if any one knows any good library for doing this, then provide me the link for them.

  • Avtar Guleria
    Avtar Guleria over 10 years
    That workaround didn't work for me..:(. If I scroll with higher velocity it moves me to the next slide.
  • Mike Ortiz
    Mike Ortiz over 10 years
    @AvtarGuleria Did the other workaround included in my edit help? I know I've successfully employed it in the past.
  • Avtar Guleria
    Avtar Guleria over 10 years
    No Second workaround too not worked for me. Whenever i scroll horizontally, It just moves me to the second slide. But if I scroll vertically or at some other angle other than horizontal it works..so, Again Horizontally it doesn't work...
  • Mike Ortiz
    Mike Ortiz over 10 years
    Ok, I will take a look at it again and provide more thorough example code.
  • Mike Ortiz
    Mike Ortiz over 10 years
    What is the API you are testing on? I know this works with API > 14, though I am having some issues with a gingerbread device.
  • Mike Ortiz
    Mike Ortiz over 10 years
    @AvtarGuleria The first workaround I linked was correct, it just needed to be adapted to work with TouchImageView. I've included my complete working code in the answer above. Tested on a gingerbread and ICS devices. Let me know if you still have troubles with it.
  • Avtar Guleria
    Avtar Guleria over 10 years
    Thanks for the updated code, I will try it and let you know. I am providing support for API >= 9. And For your first workaround I have also used with your Github Touch Image view project, But that didn't work for me. But as mentioned in my previous comment your second workaround seems worked but not 100% as explained in my previous comment.
  • AsafK
    AsafK over 10 years
    Im trying to implement your solution, with canScrollHorizontally() or with the solution in the last link on your answer, but it doesnt work. The ViewPager always moves to the next page when horizontally scrolled.
  • AsafK
    AsafK over 10 years
    The problem is that computeHorizontalScrollRange() and computeHorizontalScrollExtent() are always equal.
  • Mike Ortiz
    Mike Ortiz over 10 years
    @AsafK 1. Make sure you are using code from the dev branch (not master). You can confirm this by seeing that TouchImageView overrides canScrollHorizontally. 2. You can ignore the second link. My example code above is an adaptation of the code in that link for TouchImageView rather than WebView. 3. I and at two other StackOverflow users have confirmed the example code above works. Make sure your implementation exactly follows mine.
  • AsafK
    AsafK over 10 years
    @MikeOrtiz Ok, I took the dev branch version and it works. But now there's a different problem - with the master branch version zooming the image was also increasing the imageview size so that it fills the entire screen. Now when i zoom the image is scaling but the imageview stays the same size. is this configurable ?
  • AsafK
    AsafK over 10 years
    @MikeOrtiz do you see what im talking about ?
  • Mike Ortiz
    Mike Ortiz over 10 years
    @AsafK No, I'm not seeing your problem. For me, it works as expected. Can you post a bug on github. Could you include all relevant code in separate pastebin links, as well as device and os version? Thanks.
  • AsafK
    AsafK over 10 years
  • Mike Ortiz
    Mike Ortiz over 10 years
    @AsafK Thank you for the response. Your pastebin link is private.
  • Erum
    Erum over 10 years
    can someone please help me how to use this code so that i can show multiple images in Pager with zoom in and zoom out functionality using buttons (which is already working) but the only problem is to use ViewPager can someone provide me latest code
  • Justin
    Justin about 10 years
    This solution didn't work for me either. The zooming in/out is very awkward, most of the time it doesn't do anything and when it does it isn't natural (doesn't follow the amount you moved your fingers.) Also, after resizing an image and going to next slide, after going back the image has disappeared. It's disappointing because I spent all morning porting the code from java to C# Xamarin. :(
  • Justin
    Justin about 10 years
    Here is the Xamarin code in case anyone else wants to play with it further and try to get it working... gist.github.com/justintoth/10663869
  • Mike Ortiz
    Mike Ortiz about 10 years
    @Justin It sounds like you may be using the code on master which does not yet support view pager and has some other bugs in it. Did you try with the dev branch? Also, I will soon be adding other examples to the sample app including view pager. The examples should be on dev in the next couples days and master soon after.
  • Erum
    Erum about 10 years
    @MikeOrtiz can u please paste link here with TouchImageView with ViewPager i need this i have already worked on zoomin and zoomout btn part but the only thing left is to integrate paging with them can u please post touchimageview+pager dev branch link here
  • Mike Ortiz
    Mike Ortiz about 10 years
    Here is a link to an example ViewPager implementation. It is currently on the master branch as of v1.2.0.
  • Giru Bhai
    Giru Bhai almost 10 years
    @MikeOrtiz Thanks a lot.+1 for update with view pager.
  • Shadow
    Shadow almost 10 years
    After zooming and swiping the view pager to next image and if I swipe back to previous image, that image not appearing to original position
  • Ruslan Mansurov
    Ruslan Mansurov almost 10 years
    ViewPager doesn't destroy previous image from memory, so when you are moving back ViewPager just shows object with saved state. In order to reset zoom you may use ImageViewTouch's method resetDisplay or any other suitable for you method.
  • Shadow
    Shadow almost 10 years
    yes i used @Master but not worked. stackoverflow.com/questions/25760505/…
  • Muhammad Younas
    Muhammad Younas over 8 years
    @Mike Ortiz I successfully implement your library but i want few changes and i want that when image is zoom than i restrict the viewpager from swipping or when user press the back key and if image is in zoom state than image should come in default state