Android之Matrix学习(一)

来源:互联网 发布:免费erp软件 编辑:程序博客网 时间:2024/06/02 02:26

使用Matrix实现图片移动和多点触摸

一、什么是Matrix?其实在Android中Matrix本质是一个3*3的矩阵
Matrix包括的图形处理包括以下4种。
-Translate 平移变换
-scale 缩放变换
-rotate 旋转变换
-skew 错切变换
前面三个比较容易理解,有点类似于动画中的变化,就不做介绍了,最后一个错切变化在数学上又称为Shear mapping或者Transvection,它是一种比较特殊的线性变换。错切变换的效果就是让所有点的X坐标(或者Y坐标)保持不变,让Y(X)坐标进行按比例发生平移,而且平移的大小和该点到X(Y)周的垂直距离成正比。错切变换的公式如下:

x = x0 + K1 * y0
y=K2*x0+y0

这篇博客用的技术只用到了Matrix的平移变换,其它的在后续会讲到。
OK,上代码。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#000"    tools:context="${relativePackage}.${activityClass}" >    <ImageView        android:id="@+id/iv"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scaleType="matrix"        android:src="@drawable/img" /></RelativeLayout>

这个布局中只有一个ImageView,注意:要想让图片可以通过Matrix实现变化,必须加这行代码,否则不会起作用。

android:scaleType=”matrix”

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mIv = (ImageView) findViewById(R.id.iv);        mStartPoint = new PointF();         matrix = new Matrix();         mCurrentMatrix = new Matrix();        mIv.setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getActionMasked()) {                case MotionEvent.ACTION_DOWN:                    //将模式改为拖拽                    mode = DRAG ;                    //当手指按下的时候,记录一开始按下的位置                    mCurrentMatrix.set(mIv.getImageMatrix());                    mStartPoint.x = event.getX();                    mStartPoint.y = event.getY() ;                    break;                case MotionEvent.ACTION_MOVE:                    if(mode == DRAG){                        //计算移动的距离                        float dx = event.getX() - mStartPoint.x ;                        float dy = event.getY() - mStartPoint.y;                        //在没有移动的基础上开始移动                        matrix.set(mCurrentMatrix);                        matrix.set(mCurrentMatrix);                         //利用矩阵移动                        matrix.postTranslate(dx, dy) ;                    }else if(mode == ZOOM){                        mMoveInstance = distance(event);                        //计算缩放比例                        float scale = mMoveInstance / mStartInstance ;                        centerP = calculateCenter(event);                        //基于上一次的放大倍数基础上进行缩放                        matrix.set(mCurrentMatrix);                        System.out.println("scale:" + scale );                        matrix.postScale(scale, scale, centerP.x  , centerP.y ) ;                    }                    break;                //在第二根手指按下的时候计算此时的距离                case MotionEvent.ACTION_POINTER_DOWN:                    mStartInstance = distance(event);                    centerP = calculateCenter(event);                    //记录当前的矩阵                    mCurrentMatrix.set(mIv.getImageMatrix());                     //将模式改为缩放                    mode = ZOOM ;                    break;                case MotionEvent.ACTION_UP:                case MotionEvent.ACTION_POINTER_UP:                    mode = 0 ;                    break;                }                mIv.setImageMatrix(matrix);                return true;//将事件消费            }        });    }

可能有些童鞋不太了解event.getActionMasked(),其实,我们点进去看源码知道点了

public final int getActionMasked() {
return nativeGetAction(mNativePtr) & ACTION_MASK;
}

而getAction()的源码如下:

public final int getAction() {
return nativeGetAction(mNativePtr);
}

ACTION_MASK到底是什么呢?

/**
* Bit mask of the parts of the action code that are the action itself.
*/
public static final int ACTION_MASK = 0xff;

protected PointF calculateCenter(MotionEvent event) {        float dx = event.getX(1) + event.getX(0);        float dy = event.getY(1)+event.getY(0);        return new PointF(dx / 2 ,dy / 2);    }
protected float distance(MotionEvent event) {        float x = event.getX(1) - event.getX(0);        float y = event.getY(1) - event.getY(0);        return (float) Math.sqrt(x * x + y * y) ;    }

由此可以看出getActionMasked()就相当于getAction()&&255,相当于将高位屏蔽掉了。总之,记住,要想实现多点触摸,就使用getActionMasked()。然后就是每次按下的时候需要设置下当前图片的矩阵值,使在移动的时候在此基础上进行移动.其它的就没有太难的地方,在草稿纸上画画就应该出来了

运行结果:

这里写图片描述

源码下载

2 0