转自:http://www.111cn.net/sj/android/53678.htm


本文章来给各位同学介绍一下Android开发之ImageView通过matrix实现手势缩放操作方法,我们知道安卓中ImageView本身有scaleType属性,通过设置android:scaleType=matrix 可以用很少的代码就实现缩放功能了,下面我们来看看。

关于ImageView的手势缩放,有很多种方法,绝大多数开源自定义缩放都是修改了ondraw函数来实现的。但是ImageView本身有scaleType属性,通过设置android:scaleType="matrix" 可以用很少的代码就实现缩放功能。缩放的优点是实现起来简单,同时因为没有反复调用ondraw函数,缩放过程中不会有闪烁现象。

MATRIX矩阵可以动态缩小放大图片来显示,缩小图片:

代码如下 复制代码

//获得Bitmap的高和宽
int bmpWidth=bmp.getWidth();
int bmpHeight=bmp.getHeight();

//设置缩小比例
double scale=0.8;
//计算出这次要缩小的比例
scaleWidth=(float)(scaleWidth*scale);
scaleHeight=(float)(scaleHeight*scale);

//产生resize后的Bitmap对象
Matrix matrix=new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizeBmp=Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, true);

下面将一个自定义的实现了手势缩放的ImageView代码拷贝如下:

代码如下 复制代码

package com.jcodecraeer.stargallerry;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.widget.ImageView;
public class ImageTouchView extends ImageView {

private PointF startPoint = new PointF();
private Matrix matrix = new Matrix();
private Matrix currentMaritx = new Matrix();

private int mode = 0;//用于标记模式
private static final int DRAG = 1;//拖动
private static final int ZOOM = 2;//放大
private float startDis = 0;
private PointF midPoint;//中心点

/**
* 默认构造函数
* @param context
*/
public ImageTouchView(Context context){
super(context);
}
/**
* 该构造方法在静态引入XML文件中是必须的
* @param context
* @param paramAttributeSet
*/
public ImageTouchView(Context context,AttributeSet paramAttributeSet){
super(context,paramAttributeSet);
}

public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mode = DRAG;
currentMaritx.set(this.getImageMatrix());//记录ImageView当期的移动位置
startPoint.set(event.getX(),event.getY());//开始点
break;
case MotionEvent.ACTION_MOVE://移动事件

if (mode == DRAG) {//图片拖动事件
float dx = event.getX() - startPoint.x;//x轴移动距离
float dy = event.getY() - startPoint.y;
matrix.set(currentMaritx);//在当前的位置基础上移动
matrix.postTranslate(dx, dy);

} else if(mode == ZOOM){//图片放大事件
float endDis = distance(event);//结束距离
if(endDis > 10f){
float scale = endDis / startDis;//放大倍数
//Log.v("scale=", String.valueOf(scale));
matrix.set(currentMaritx);
matrix.postScale(scale, scale, midPoint.x, midPoint.y);
}


}
break;

case MotionEvent.ACTION_UP:
mode = 0;
break;
//有手指离开屏幕,但屏幕还有触点(手指)
case MotionEvent.ACTION_POINTER_UP:
mode = 0;
break;
//当屏幕上已经有触点(手指),再有一个手指压下屏幕
case MotionEvent.ACTION_POINTER_DOWN:
mode = ZOOM;
startDis = distance(event);

if(startDis > 10f){//避免手指上有两个茧
midPoint = mid(event);
currentMaritx.set(this.getImageMatrix());//记录当前的缩放倍数
}

break;
}
this.setImageMatrix(matrix);
return true;
}

/**
* 两点之间的距离
* @param event
* @return
*/
private static float distance(MotionEvent event){
//两根线的距离
float dx = event.getX(1) - event.getX(0);
float dy = event.getY(1) - event.getY(0);
return FloatMath.sqrt(dx*dx + dy*dy);
}
/**
* 计算两点之间中心点的距离
* @param event
* @return
*/
private static PointF mid(MotionEvent event){
float midx = event.getX(1) + event.getX(0);
float midy = event.getY(1) - event.getY(0);

return new PointF(midx/2, midy/2);
}
}


在xml中这样使用自定义的ImageView:

<com.jcodecraeer.stargallerry.ImageTouchView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
/>

这里有个小细节, android:layout_width和android:layout_height这里都是="match_parent" ,如果我们换成wrap_content的话,你会发现图片只能在一个很小的区间缩放。而match_parent则可以很随意的在整个屏幕缩放。

但是match_parent导致了一个让人意外的问题:

如果将imageView的宽度和高度都设置为填充整个父控件,然后scaleType设置成Matrix,则图片不是居中显示的,整个图片靠上去了,这里我还没有找出原因,不过在网上找出了解决的办法:


先设置ImageView的ScaleType="CENTER"
要给控件添加拖动与放大缩水前。再把ScaleType设为:"Matric"
(即ImageView设置OnTouchListener前更改属性即可)

其中“ImageView设置OnTouchListener前更改属性”在我们这个例子中应替换为在caseMotionEvent.ACTION_MOVE://移动事件开始更改属性。在代码中更改ScaleType应该这样做:

this.setScaleType(ImageView.ScaleType.MATRIX);

说到ScaleType,我们看看ImageView.ScaleType 值的意义和区别:

CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)

CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽

FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示

FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置

FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置

FIT_XY / fitXY 把图片不按比例扩大/缩小到View的大小显示

MATRIX / matrix 用矩阵来绘制


更多相关文章

  1. Android(安卓)使用Matrix进行图像变换
  2. android 网络下载图片 效率对比
  3. android byte[]与图片的转换
  4. android listview的divider分割线的宽度设置
  5. Flutter开始干系列-一个完整的登录实践
  6. Android(安卓)滑动效果基础篇(四)—— Gallery + GridView
  7. 第三方QQ登录不回调 (Android)
  8. Android开发技术周报 Issue#54
  9. android 默认浏览器 无法下载,此手机不支持此内容(自定义文件or AP

随机推荐

  1. Android自定义view三验证码输入控件
  2. android 输入法界面显示的开关
  3. Android和IOS开发资料
  4. Android setLayerType 硬件加速问题
  5. android studio中.9.png图片处理
  6. 给动态生成的View添加水波纹效果
  7. android 自定义PopupMenu详解
  8. Netty 长连接服务
  9. android sd卡数据库读取
  10. Android 开发之官方文档ActionBar学习记