技术联盟

Android开发学习之ImageView手势拖拽、缩放、旋转

在Android应用中,图片随手势的拖拽、缩放、旋转在很多场景中都会用到,今天我们要做的就是在ImageView的基础上实现一个可以拖拽、缩放、转转的TouchView。

 

一、实现原理

OnTouch事件捕捉+Matrix矩阵变换

二、核心方法

拖拽:Matrix.postTranslate(DeltalX, DeltalY);

缩放:Matrix.postScale(mScale, mScale, mPoint.x, mPoint.y);

旋转:Matrix.postRotate(Angle, mPoint.x, mPoint.y);

三、具体实现

package com.Android.TouchView;

/*
 * Android多点触控技术练习
 * @Author:Robin
 * @Date:2013年12月29日
 * @边界处理暂时不知道怎么写啊
 * 目前的问题有:
 * 手势识别不是很顺畅,经常出现该放缩时放缩不了的情况
 * 由于没有边界判断,程序可能会出现崩溃
 */
 
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.widget.ImageView;

@SuppressLint({ "ViewConstructor", "FloatMath" })
public class MultiTouchView extends ImageView
{


	//本地图像资源
    private int mDrawable;
    //图像位图
	private Bitmap mBitmap;
    //屏幕宽度
	private int ScreenWidth;
    //屏幕高度
	private int ScreenHeight;
    //原始图像矩阵
	private Matrix mMatrix=new Matrix();
	//过程图像矩阵
	private Matrix mSavedMatrix=new Matrix();
	//结果图像矩阵
	private Matrix mResultMatrix=new Matrix();
    //定义三种模式:None、Drag、Zoom
    public static final int Mode_None=0;
    public static final int Mode_Drag=1;
    public static final int Mode_Zoom=2;
    //当前操作模式
    private int mMode=Mode_None;
    //当前坐标
    private float mDownX,mDownY;
    //存储两点间的距离
    private float mDistance=0f;
    //存储旋转角
    @SuppressWarnings("unused")
	private float mAngle=0f;
    //存储中点
    private PointF mPoint;
    //最大缩放比例
    //private float MaxScale=3f;
    //最小缩放比例
    //private float MinScale=0.5f;
    
	public MultiTouchView(Activity mActivity ,int Drawable) 
	{
		super(mActivity);
		//设置当前图片资源
		this.mDrawable=Drawable;
		//获取Bitmap
		mBitmap=BitmapFactory.decodeResource(getResources(), mDrawable);
		DisplayMetrics dm=new DisplayMetrics();
		mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
		//获取屏幕宽度和高度
		ScreenWidth=dm.widthPixels;
		ScreenHeight=dm.heightPixels;
		mMatrix=new Matrix();
    }

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) 
	{
		//消除图像锯齿
		canvas.setDrawFilter(new PaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
		canvas.save();
		//绘制图像
		canvas.drawBitmap(mBitmap, mMatrix, null);
		canvas.restore();
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent Event)
	{
		switch(Event.getAction())
		{
		//单点触控处理
		  case MotionEvent.ACTION_DOWN:
			  //设置当前操作模式为Drag
			  mMode=Mode_Drag;
			  //获取当前坐标
			  mDownX=Event.getX();
			  mDownY=Event.getY();
              mSavedMatrix.set(mMatrix);
			  break;
		//多点触控处理
		  case MotionEvent.ACTION_POINTER_DOWN:
			     mMode=Mode_Zoom;
			     //获取两点间距离
			     mDistance=getDistance(Event);
			     //获取旋转角
			     mAngle=getAngle(Event);
			     //获取中点
			     mPoint=getMidPoint(Event);
			     mSavedMatrix.set(mMatrix);
			  break;
		  case MotionEvent.ACTION_MOVE:
			  //缩放处理
			  if(mMode==Mode_Zoom)
			  {
				  mResultMatrix.set(mSavedMatrix);
				  //获取缩放比率
				  float mScale=getDistance(Event)/mDistance;
				  //获取旋转角,这里可以不用
				  //float Angle=getAngle(Event)-mAngle;
				  //以中点为中心,进行缩放
				  mResultMatrix.postScale(mScale, mScale, mPoint.x, mPoint.y);
				  //以中点为中心,进行旋转,这里可以不用
				  //mResultMatrix.postRotate(Angle, mPoint.x, mPoint.y);
				  mMatrix.set(mResultMatrix);
				  invalidate();
			  }else if(mMode==Mode_Drag)//平移处理
			  {
				  mResultMatrix.set(mSavedMatrix);
				  //计算平移量
				  float DeltalX=Event.getX()-mDownX;
				  float DeltalY=Event.getY()-mDownY;
				  //平移
				  mResultMatrix.postTranslate(DeltalX, DeltalY);
				  mMatrix.set(mResultMatrix);
				  invalidate();
			  }
			  break;
		  
		  case MotionEvent.ACTION_UP:
			 //这里要不要处理呢,如果需要,怎么办
		  case MotionEvent.ACTION_POINTER_UP:
				mMode = Mode_None;
				break;
		}
		return true;
	}

	//返回两点间的距离
	public float getDistance(MotionEvent Event)
	{
		//计算X的变化量
		float DeltalX=Event.getX(0)-Event.getX(1);
		//计算Y的变化量
		float DeltalY=Event.getY(0)-Event.getY(1);
		//计算距离
		return FloatMath.sqrt(DeltalX*DeltalX+DeltalY*DeltalY);
	}
	
	//返回两点的中点
	@SuppressLint("FloatMath")
	public PointF getMidPoint(MotionEvent Event)
	{
		float X=Event.getX(0)+Event.getX(1);
		float Y=Event.getY(0)+Event.getY(1);
		return new PointF(X/2,Y/2);
	}
	
	//获得旋转角
	public float getAngle(MotionEvent Event)
	{
		double DeltalX=Event.getX(0)-Event.getX(1);
		double DeltalY=Event.getY(0)-Event.getY(1);
		return (float)Math.atan2(DeltalX, DeltalY);
	}
	
	//边界处理,暂时没找到比较好的方法
	public boolean CheckBounary()
	{
		return false;
	}
	
	//存储当前图片
	public Bitmap SaveImage()
	{
		Bitmap mBitmap = Bitmap.createBitmap(ScreenWidth, ScreenHeight,Config.ARGB_8888);
		Canvas mCanvas = new Canvas(mBitmap); 
		mCanvas.drawBitmap(mBitmap, mMatrix, null);
		mCanvas.save(Canvas.ALL_SAVE_FLAG);
		mCanvas.restore();
		return mBitmap;
	}
}

 

四、 运行效果

Share this:

码字很辛苦,转载请注明来自技术联盟《Android开发学习之ImageView手势拖拽、缩放、旋转》

评论