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

四、 运行效果



更多相关文章

  1. 使用android的加速度计移动图像
  2. Android如何缩放应用中的字体大小
  3. 在不同状态下使用两个图像切换按钮
  4. android 关于webview缩放和适应屏幕的问题
  5. 3D相机缩放并遵循java中的物理特性?
  6. POST json和图像到服务器android
  7. Java实现图像对比类
  8. 为可执行文件夹提供自定义图像
  9. 在扑克游戏中显示卡片的图像

随机推荐

  1. Android日记抓取并保存
  2. Android Studio 布局属性笔记
  3. Android控件笔记——在界面中显示及输入
  4. Android 常用开发工具以及Mac常用软件
  5. 自定义动画(animation)时set中的各元素效
  6. 相对布局相关属性
  7. [Android 博客]收集一些不错的,关于androi
  8. android应用自定义字体
  9. Android 控件使用参数集锦
  10. Android架构组件-Lifecycle