Android手势检测 带你打造图片缩放预览(上)

在进入正题钱我们需要作一些准备工作,本文用到了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的平移矩阵
matrix.postTranslate(x,y,cx,cy):表示以(cx,cy)为缩放中心水平方向缩放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手势检测 带你打造支持图片缩放、平移预览(下)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值