在进入正题钱我们需要作一些准备工作,本文用到了Matrix , ScaleGestureDetector ,Metrix用来控制图片的缩放、平移等错,ScaleGestureDetector用于检测缩放手势。如果对以上两个东东不了解只能字节去查找相关的知识点了,这里不做过多描述。
效果图:因为文件图片不能大于2M所以画面质量、流畅度都不怎么好。
先贴出全部代码,一共三部分
//1、setSCale(x,y)是对单位矩阵进行操作、postScale(x,y)是对当前矩阵进行操作,对当前矩阵起到缩放(x,y)的效果、preScale(x,y)则不能起到缩放(x,y)的效果 //2、mapRectF(rect)用当前matrix对rect进行处理(与图片一样,缩放,平移,旋转) import com.solo.imageviewer.tools.ImagePositonManager; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector.OnScaleGestureListener; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; class ScaleImageViewer extends ImageView implements OnTouchListener,OnScaleGestureListener{ private ScaleGestureDetector sgc; private static final float MAX_SCALE=4.0F; private static final float MIN_SCALE=0.2F; private Matrix matrix=new Matrix(); private float[] values=new float[9]; private boolean once=true; public ScaleImageViewer(Context context, AttributeSet attrs) { super(context, attrs); super.setScaleType(ScaleType.MATRIX); this.setOnTouchListener(this); sgc=new ScaleGestureDetector(context, this); } public ScaleImageViewer(Context context) { this(context,null); } @Override public boolean onScale(ScaleGestureDetector detector) { float scaleFactor=detector.getScaleFactor(); float currentScale=getScale();//相对原图的缩放比例 if(currentScale>MAX_SCALE && scaleFactor<1.0f || currentScale<MIN_SCALE && scaleFactor>1.0f || currentScale<MAX_SCALE && currentScale>MIN_SCALE){ matrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); } ImagePositonManager.setShowPosition(getDrawable(), matrix, getWidth(), getHeight()); setImageMatrix(matrix); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { return sgc.onTouchEvent(event);//这里的event会触发onScale的执行 } @Override protected void onDraw(Canvas canvas) { if(once){ matrix=getImageMatrix(); once=false; Drawable drawable=getDrawable(); //获取图片的宽和高 int dw=drawable.getIntrinsicWidth(); int dh=drawable.getIntrinsicHeight(); int w=getWidth(); int h=getHeight(); float scale=Math.min(1.0f*w/dw, 1.0f*h/dh); matrix.postTranslate(w/2-dw/2, h/2-dh/2); matrix.postScale(scale, scale, w/2, h/2); setImageMatrix(matrix); } super.onDraw(canvas); } private float getScale(){ matrix.getValues(values); return values[Matrix.MSCALE_X]; } }
public class ImagePositonManager { public static void setShowPosition(Drawable drawable,Matrix matrix,int w,int h){ RectF rectF=new RectF(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); matrix.mapRect(rectF); float rw=rectF.width(); float rh=rectF.height(); float moveX=0,moveY=0; if(rw<w){ moveX=w/2-rw/2-rectF.left; } if (rh<h) { moveY=h/2-rh/2-rectF.top; } if(rw>w && rectF.left>0){ moveX=-rectF.left; } if(rw>w && rectF.right<w){ moveX=w-rectF.right; } if(rh>h && rectF.top>0){ moveY=-rectF.top; } if(rh>h && rectF.bottom<h){ moveY=h-rectF.bottom; } matrix.postTranslate(moveX, moveY); } }
现在对代码进行分析
protected void onDraw(Canvas canvas) { if(once){ matrix=getImageMatrix(); once=false; Drawable drawable=getDrawable(); //获取图片的宽和高 int dw=drawable.getIntrinsicWidth(); int dh=drawable.getIntrinsicHeight(); int w=getWidth(); int h=getHeight(); float scale=Math.min(1.0f*w/dw, 1.0f*h/dh); matrix.postTranslate(w/2-dw/2, h/2-dh/2); matrix.postScale(scale, scale, w/2, h/2); setImageMatrix(matrix); } super.onDraw(canvas); }我们在onDraw方法中来控制图片初始显示时的大小位置,由于onDraw后图片才会显示到手机上,所以我们在这里进行图片初始显示的一些操作完全来的及
Drawable drawable=getDrawable(); //获取图片的宽和高 int dw=drawable.getIntrinsicWidth(); int dh=drawable.getIntrinsicHeight();
以上代码可以获得原图的宽和高,注意是原图,这个不会随着你缩放图片而改变
matrix.postTranslate(w/2-dw/2, h/2-dh/2); matrix.postScale(scale, scale, w/2, h/2);matrix.postTtranslate(x,y):b表示一个水平方向平移x竖直方向平移y的平移矩阵
setImageMatrix(matrix);将矩阵作用到图片,这一步完成后就对图片进行了移动和缩放操作
private float getScale(){ matrix.getValues(values); return values[Matrix.MSCALE_X]; }用上面的getScale来获取当前的缩放比例,注意是相对于原图
ImagePositonManager.setShowPosition(getDrawable(), matrix, getWidth(), getHeight());
调整图片显示的位置,这个要在setImageMatrix之前调用RectF rectF=new RectF(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); matrix.mapRect(rectF); <span style="font-family: Arial, Helvetica, sans-serif;">float rw=rectF.width(); </span><span style="font-family: Arial, Helvetica, sans-serif;">float rh=rectF.height();</span>
用来获取当前图片的狂和高,这时候图片还没有显示出来,当时matrix已经准备好了所以这里相当于是提前获得图片的宽和高,以便进行位置调整
ok所有的代买已经讲解完毕!注意这里的图片缩放都是以屏幕中心为准的额,下一篇Android手势检测 带你打造支持图片缩放、平移预览(下)