viewPager+photoView实现图片轮播和手势缩放功能 支持手势缩放的imageView 如何实现相册左右滑动和手势缩放 如何让图片自适应控件大小 photoView如何使用(上)

原创 2016年06月01日 21:38:19

       很多朋友都可能遇到这这个问题,实现一个支持手势缩放的图片轮播功能。就像我们的手机相册一样。而且有时候还需要让图片拉伸自动充满全屏。

       图片轮播我们自然而然,想到了viewPager+imageView来实现,但是想要实现手势缩放就遇到了很大的难度,imageView根本不支持缩放。


       那么打造支持手势缩放的imageView那肯定就需要自定义了,网上有很多这样的自定义view我们可以直接拿来用,可以有一个问题就是,这样的自定义imageView很多的手势操作会和ViewPager的手势操作冲突,那么我们怎样来解决这个问题了?


答案:用开源框架photoView

  • 支持单点/多点触摸,即时缩放图片;
  • 支持平滑滚动;
  • 在滑动父控件下能够运行良好;(例如:ViewPager)
  • 当用户的触点改变是可以触发通知
       当和ViewPager嵌套使用的时候,放大缩小会出现一个异常:IllegalArgumentException: pointerIndex out of range.
       这是Android ViewPager的一个BUG
       这里可以更改为HackyViewPager,它是继承的ViewPaer.

下面我们就来一步一步教大家如何使用photoViewHackyViewPager

1.创建一个类PhotoView,然后复制下面代码放到这个类中。

import uk.co.senab.photoview.IPhotoView;
import uk.co.senab.photoview.PhotoViewAttacher;
import uk.co.senab.photoview.PhotoViewAttacher.OnMatrixChangedListener;
import uk.co.senab.photoview.PhotoViewAttacher.OnPhotoTapListener;
import uk.co.senab.photoview.PhotoViewAttacher.OnViewTapListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

public class PhotoView extends ImageView implements IPhotoView {

    private final PhotoViewAttacher mAttacher;
    private ScaleType mPendingScaleType;

    public PhotoView(Context context) {
        this(context, null);
    }

    public PhotoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        super.setScaleType(ScaleType.MATRIX);
        mAttacher = new PhotoViewAttacher(this);
        if (null != mPendingScaleType) {
            setScaleType(mPendingScaleType);
            mPendingScaleType = null;
        }
    }

    public PhotoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @Override
    public boolean canZoom() {
        // TODO Auto-generated method stub
        return mAttacher.canZoom();
    }

    @Override
    public Matrix getDisplayMatrix() {
        // TODO Auto-generated method stub
        return mAttacher.getDrawMatrix();
    }

    @Override
    public RectF getDisplayRect() {
        // TODO Auto-generated method stub
        return mAttacher.getDisplayRect();
    }

    @Override
    public IPhotoView getIPhotoViewImplementation() {
        // TODO Auto-generated method stub
        return mAttacher;
    }

    @Override
    public float getMaxScale() {
        // TODO Auto-generated method stub
        return getMaximumScale();
    }

    @Override
    public float getMaximumScale() {
        // TODO Auto-generated method stub
        return mAttacher.getMaximumScale();
    }

    @Override
    public float getMediumScale() {
        // TODO Auto-generated method stub
        return mAttacher.getMediumScale();
    }

    @Override
    public float getMidScale() {
        // TODO Auto-generated method stub
        return getMediumScale();
    }

    @Override
    public float getMinScale() {
        // TODO Auto-generated method stub
        return getMinimumScale();
    }

    @Override
    public float getMinimumScale() {
        // TODO Auto-generated method stub
        return mAttacher.getMinimumScale();
    }

    @Override
    public OnPhotoTapListener getOnPhotoTapListener() {
        // TODO Auto-generated method stub
        return mAttacher.getOnPhotoTapListener();
    }

    @Override
    public OnViewTapListener getOnViewTapListener() {
        // TODO Auto-generated method stub
        return mAttacher.getOnViewTapListener();
    }

    @Override
    public float getScale() {
        // TODO Auto-generated method stub
        return mAttacher.getScale();
    }

    @Override
    public Bitmap getVisibleRectangleBitmap() {
        // TODO Auto-generated method stub
        return mAttacher.getVisibleRectangleBitmap();
    }

    @Override
    public void setAllowParentInterceptOnEdge(boolean allow) {
        // TODO Auto-generated method stub
        mAttacher.setAllowParentInterceptOnEdge(allow);
    }

    @Override
    public boolean setDisplayMatrix(Matrix finalMatrix) {
        // TODO Auto-generated method stub
        return mAttacher.setDisplayMatrix(finalMatrix);
    }

    @Override
    public void setMaxScale(float maxScale) {
        // TODO Auto-generated method stub
        mAttacher.setMaxScale(maxScale);
    }

    @Override
    public void setMaximumScale(float maximumScale) {
        // TODO Auto-generated method stub
        mAttacher.setMaximumScale(maximumScale);
    }

    @Override
    public void setMediumScale(float mediumScale) {
        // TODO Auto-generated method stub
        mAttacher.setMediumScale(mediumScale);
    }

    @Override
    public void setMidScale(float midScale) {
        // TODO Auto-generated method stub
        mAttacher.setMidScale(midScale);
    }

    @Override
    public void setMinScale(float minScale) {
        // TODO Auto-generated method stub
        mAttacher.setMinScale(minScale);
    }

    @Override
    public void setMinimumScale(float minimumScale) {
        // TODO Auto-generated method stub
        mAttacher.setMinimumScale(minimumScale);
    }

    @Override
    public void setImageResource(int resId) {
        // TODO Auto-generated method stub
        super.setImageResource(resId);
        if (null != mAttacher) {
            mAttacher.update();
        }
    }

    @Override
    public void setImageURI(Uri uri) {
        // TODO Auto-generated method stub
        super.setImageURI(uri);
        if (null != mAttacher) {
            mAttacher.update();
        }
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        // TODO Auto-generated method stub
        super.setImageDrawable(drawable);
        if(null !=mAttacher){
            mAttacher.update();
        }
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        // TODO Auto-generated method stub
        super.setImageBitmap(bm);
        if(null !=mAttacher){
            mAttacher.update();
        }
    }

    @Override
    public void setOnDoubleTapListener(
            OnDoubleTapListener newOnDoubleTapListener) {
        // TODO Auto-generated method stub
        mAttacher.setOnDoubleTapListener(newOnDoubleTapListener);
    }

    @Override
    public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
        // TODO Auto-generated method stub
        mAttacher.setOnMatrixChangeListener(listener);
    }

    @Override
    public void setOnPhotoTapListener(OnPhotoTapListener listener) {
        // TODO Auto-generated method stub
        mAttacher.setOnPhotoTapListener(listener);
    }

    @Override
    public void setOnLongClickListener(OnLongClickListener listener) {
        // TODO Auto-generated method stub
        mAttacher.setOnLongClickListener(listener);
    }

    @Override
    public void setOnViewTapListener(OnViewTapListener listener) {
        // TODO Auto-generated method stub
        mAttacher.setOnViewTapListener(listener);
    }

    @Override
    public void setPhotoViewRotation(float rotationDegrees) {
        // TODO Auto-generated method stub
        mAttacher.setRotationTo(rotationDegrees);
    }

    @Override
    public void setRotationBy(float rotationDegrees) {
        // TODO Auto-generated method stub
        mAttacher.setRotationBy(rotationDegrees);
    }

    @Override
    public void setRotationTo(float rotationDegrees) {
        // TODO Auto-generated method stub
        mAttacher.setRotationTo(rotationDegrees);
    }

    @Override
    public void setScale(float scale) {
        // TODO Auto-generated method stub
        mAttacher.setScale(scale);
    }

    @Override
    public void setScale(float scale, boolean animate) {
        // TODO Auto-generated method stub
        mAttacher.setScale(scale, animate);
    }

    @Override
    public void setScale(float scale, float focalX, float focalY,
            boolean animate) {
        // TODO Auto-generated method stub
        mAttacher.setScale(scale, focalX, focalY, animate);
    }

    @Override
    public void setZoomTransitionDuration(int milliseconds) {
        // TODO Auto-generated method stub
        mAttacher.setZoomTransitionDuration(milliseconds);
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (null != mAttacher) {
            mAttacher.setScaleType(scaleType);
        } else {
            mPendingScaleType = scaleType;
        }
    }

    @Override
    public void setZoomable(boolean zoomable) {
        // TODO Auto-generated method stub
        mAttacher.setZoomable(zoomable);
    }

    @Override
    protected void onDetachedFromWindow() {
        // TODO Auto-generated method stub
        mAttacher.cleanup();
        super.onDetachedFromWindow();
    }

}


2.创建类HackyViewPager,将下面代码复制进去

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Hacky fix for Issue #4 and
 * http://code.google.com/p/android/issues/detail?id=18990
 * 
 * ScaleGestureDetector seems to mess up the touch events, which means that
 * ViewGroups which make use of onInterceptTouchEvent throw a lot of
 * IllegalArgumentException: pointerIndex out of range.
 * 
 * There's not much I can do in my code for now, but we can mask the result by
 * just catching the problem and ignoring it.
 * 
 * @author Chris Banes
 */
/**
 * 自定义viewPager解决和photoView滑动的冲突事件
 * @author Administrator
 *
 */
public class HackyViewPager extends ViewPager {

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

	public HackyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		try {
			return super.onInterceptTouchEvent(ev);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			return false;
		}
	}

}

   3.在显示界面的布局文件中添加一个自定义的HackyViewPager


  <com.xixiangfu.photoview.HackyViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

4.在activity中写代码,创建一个数据源,我这里用的是本地图片,放在drawable文件夹,建立了一个数组,将图片Id添加进去。
private int[] photoId = { R.drawable.kejiqianyan_02, R.drawable.chezai_01,R.drawable.shumadianzi_02 }

5.初始化自定义的HackyViewPager,然后给其设置PagerAdapter适配器。在onCreate中给viewPager设置adapter.如下
   viewPager = (ViewPager) findViewById(R.id.viewPager);

   这个适配器需要自定义,所有photoView的创建和图片设置都在这里完成操作,具体见代码。
   而且要特别注意是,一定要重写1.  instantiateItem()方法,2.  destroyItem()方法 3. isViewFromObject()方法。
   其中方法2和3的写法一般是固定的,按照下面代码中的写就可以了,方法1的话可以按照下面代码里的写,就可以实现图片的正常展示了。    如果还需要设置图片的属性的话,可以在这里直接设置,和imageView的属性是一样的。

     例如需要让图片拉伸充满全屏,photoView.setScaleType(ScaleType.FIT_XY);  //设置充满全屏

<pre name="code" class="java">/**
	 * 自定义pagerAdapter
	 */
	public class MyAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			return photoId.length;
		}
		  @Override
	        public View instantiateItem(ViewGroup container, int position) {
	            PhotoView photoView = new PhotoView(container.getContext());
	            container.addView(photoView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
	            photoView.setImageResource(photoId[position]);
	            photoView.setScaleType(ScaleType.FIT_XY);//设置图片显示为充满全屏
	            return photoView;
	        }

	        @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;
	        }
	}



然后就可以运行这个程序了,效果很不错,但是还有一个问题,当前图片放大后,滑动到下一页,滑回来之后,当前页面的图片还是处于放大状态,没有恢复默认大小,这样用户体验非常不好,下一篇文章我会给出解决方法。


这里是eclipse使用的photoView的jar包下载地址
http://download.csdn.net/detail/beibaokongming/9540545

版权声明:本文为背包客孔明先生原创文章,未经博主允许不得转载。

相关文章推荐

PhotoView开源项目剖析

介绍 上一节呢,我们介绍了怎么下载和编译Android源码,这节呢,我们来讨论PhotoView这个开源项目,也是我们用的非常频繁的一个,用来帮助产生一个容易实现ImageView缩放的这么个东东。 ...

android photoview 图片放大缩放功能 ImageView

android 图片浏览功能 图片放大缩小 使用 photoview 双击或双指缩放的ImageView 使用多点触控和双击。 滚动,以平滑滚动甩。 github 下载地址: https...
  • aaawqqq
  • aaawqqq
  • 2015年01月25日 23:49
  • 51478

Android 手势图片,强大的开源框架PhotoView

查看图片是每个APP上非常重要的一个部分,而在开源框架中非常好用的一个查看图片的框架就是PhotoView了。这个框架其实设计的是非常巧妙的,这篇文章主要就是从源码的角度来讲解这个框架的实现。 ...
  • mybeta
  • mybeta
  • 2014年11月21日 16:41
  • 3791

PhotoView的使用--Android开发之点击图片放大的功能

今天的认识了一个开源代码PhotoView,主要就是实现图片点击放大的功能,那么这个玩意儿怎么使用呢, 第一步1.Gradle添加依赖 (推荐)dependencies { compile ...

开源库PhotoView修改二级双击放大

[TOC] 图片缩放 https://github.com/chrisbanes/PhotoView 修改双击直接放到最大,取消二次双击 缩放异常处理 修改双击直接放到最大,取消二次双击找到...

使用ViewPager和Photoview实现图片左右滑动和放大缩小

为了实现图片的左右滑动以及放大缩小的功能,用到了两个组件ViewPager和PhotoView。 PhotoView是开源项目,它也是通过继承ImageView然后扩充功能,实现图片放大缩小等功能;而...

Android中图片放大缩小(和ViewPager配合使用流畅显示)--第三方开源--PhotoView

时间 2015-11-28 23:49:00  博客园-原创精华区 原文  http://www.cnblogs.com/zzw1994/p/5003785.html 主题 ViewPager 开...

viewPager+photoView实现网络图片加载左右滑动+手势缩放功能+滑动到下一页其他页面恢复默认大小

前面两篇文章,我们讲了自定义viewpager+photoView实现本地图片的加载和收缩缩放。实现本地相册功能。 如果没有看的话可以先阅读以下,因为今天网络加载图片的功能,实在这个基础上做...

使用photoview+viewpager实现图片缩放切换(类似微信朋友圈图片查看)

使用Imageloader+CircleImageview+PhotoView+ViewPager实现类似微信朋友圈效果,图片缩放查看以及切换。。。...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:viewPager+photoView实现图片轮播和手势缩放功能 支持手势缩放的imageView 如何实现相册左右滑动和手势缩放 如何让图片自适应控件大小 photoView如何使用(上)
举报原因:
原因补充:

(最多只允许输入30个字)