android Matrix图片的缩放和拖动

              开发中经常遇到图片的大小超过手机屏幕的大小,或者图片过小,在手机上显示出来太小,这时候我们就需要对图片进行放大缩小或者拖动。

         android为ImageView提供了scaleType的属性,在scaleType的属性值有多种,大部分是根据高和宽经行缩放,但是无法动态的缩放,只有matrix是可以进行动态缩放的,所以我们在这之前有必要了解一下matrix属性。

       Matrix主要用于对平面进行平移(Translate),缩放(Scale),旋转(Rotate)以及斜切(Skew)操作。为简化矩阵变换,Android封装了一系列方法来进行矩阵变换;其中包括:

set系列方法:setTranslate,setScale,setRotate,setSkew;设置,会覆盖之前的参数。
pre系列方法:preTranslate,preScale,preRotate,preSkew;矩阵先乘,如M' = M * T(dx, dy)。
post系列方法:postTranslate,postScale,postRotate,postSkew;矩阵后乘,如M' = T(dx, dy) * M。
通过将变换矩阵与原始矩阵相乘来达到变换的目的。

       接下来我们回到正题。首先看效果图:(有哪位大神知道真机上哪个App可以做gif图,给推荐一下。现在只能给大家一张一张的上图了,哈哈。。)

         图片顺序依次是  原图——缩略图——放大图——拖动图

android Matrix图片的缩放和拖动_第1张图片android Matrix图片的缩放和拖动_第2张图片android Matrix图片的缩放和拖动_第3张图片android Matrix图片的缩放和拖动_第4张图片


    然后就是java代码和xml布局了

   先看一下xml布局,其中android:scaleType="matrix" 非常重要。



  
   接下来就是java代码了,首先说一下思路,无非就是根据手机屏幕的点击事件(onTouch),根据手指在屏幕上的点击,移动,抬起来计算手指的位移,根据位移来进行放大缩小或者拖动,详细注释都在代码中标明,直接上代码

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MainActivity extends Activity {  
	  
    private ImageView imageView;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
  
        imageView = (ImageView) this.findViewById(R.id.imageView);  
        imageView.setOnTouchListener(new TouchListener());  
    }  
  
    private final class TouchListener implements OnTouchListener {  
          
        /** 记录是拖拉照片模式还是放大缩小照片模式 */  
        private int mode = 0;// 初始状态    
        /** 拖拉照片模式 */  
        private static final int MODE_DRAG = 1;  
        /** 放大缩小照片模式 */  
        private static final int MODE_ZOOM = 2;  
          
        /** 用于记录开始时候的坐标位置 */  
        private PointF startPoint = new PointF();  
        /** 用于记录拖拉图片移动的坐标位置 */  
        private Matrix matrix = new Matrix();  
        /** 用于记录图片要进行拖拉时候的坐标位置 */  
        private Matrix currentMatrix = new Matrix();  
      
        /** 两个手指的开始距离 */  
        private float startDis;  
        /** 两个手指的中间点 */  
        private PointF midPoint;  
  
        /** 手指点击屏幕的触摸事件*/
        @Override  
        public boolean onTouch(View v, MotionEvent event) {  
            /** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */  
            switch (event.getAction() & MotionEvent.ACTION_MASK) {  
            // 手指压下屏幕  
            case MotionEvent.ACTION_DOWN:  
                mode = MODE_DRAG;  
                // 记录ImageView当前的移动位置  
                currentMatrix.set(imageView.getImageMatrix());  
                startPoint.set(event.getX(), event.getY());  
                break;  
            // 手指在屏幕上移动,改事件会被不断触发  
            case MotionEvent.ACTION_MOVE:  
                // 拖拉图片  
                if (mode == MODE_DRAG) {  
                    float dx = event.getX() - startPoint.x; // 得到x轴的移动距离  
                    float dy = event.getY() - startPoint.y; // 得到x轴的移动距离  
                    // 在没有移动之前的位置上进行移动  
                    matrix.set(currentMatrix);  
                    matrix.postTranslate(dx, dy);  
                }  
                // 放大缩小图片  
                else if (mode == MODE_ZOOM) {  
                    float endDis = distance(event);// 结束距离  
                    if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10  
                        float scale = endDis / startDis;// 得到缩放倍数  
                        matrix.set(currentMatrix);  
                        matrix.postScale(scale, scale,midPoint.x,midPoint.y);  
                    }  
                }  
                break;  
            // 手指离开屏幕  
            case MotionEvent.ACTION_UP:  
                // 当触点离开屏幕,但是屏幕上还有触点(手指)  
            case MotionEvent.ACTION_POINTER_UP:  
                mode = 0;  
                break;  
            // 当屏幕上已经有触点(手指),再有一个触点压下屏幕  
            case MotionEvent.ACTION_POINTER_DOWN:  
                mode = MODE_ZOOM;  
                /** 计算两个手指间的距离 */  
                startDis = distance(event);  
                /** 计算两个手指间的中间点 */  
                if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10  
                    midPoint = mid(event);  
                    //记录当前ImageView的缩放倍数  
                    currentMatrix.set(imageView.getImageMatrix());  
                }  
                break;  
            }  
            imageView.setImageMatrix(matrix);  
            return true;  
        }  
  
        /** 计算两个手指间的距离 */  
        private 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);  
        }  
  
        /** 计算两个手指间的中间点 */  
        private PointF mid(MotionEvent event) {  
            float midX = (event.getX(1) + event.getX(0)) / 2;  
            float midY = (event.getY(1) + event.getY(0)) / 2;  
            return new PointF(midX, midY);  
        }  
  
    }  
  
} 


你可能感兴趣的:(原创)