您的位置:首页 > 其它

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

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

图片轮播我们自然而然,想到了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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: