美文网首页
★60.自定义控件 ★15.Matrix详解

★60.自定义控件 ★15.Matrix详解

作者: iDragonfly | 来源:发表于2017-06-29 00:21 被阅读0次

    构造方法

    Matrix ()
    Matrix (Matrix src)
    

    基本方法

    1. equals():比较两个Matrix的数值是否相同。
    2. hashCode():获取Matrix的哈希值。
    3. toString():将Matrix转换为字符串: Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
    4. toShortString():将Matrix转换为短字符串: [1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]

    数值操作

    set

    没有返回值,有一个参数,作用是将参数Matrix的数值复制到当前Matrix中。如果参数为空,则重置当前Matrix,相当于reset()

    void set (Matrix src)
    

    reset

    重置当前Matrix(将当前Matrix重置为单位矩阵)。

    void reset ()
    

    setValues

    setValues()的参数是浮点型的一维数组,长度需要大于9,拷贝数组中的前9位数值赋值给当前Matrix

    void setValues(float[] values)
    

    getValues

    参数是浮点型的一维数组,长度需要大于9,将Matrix中的数值拷贝进参数的前9位中。

    void getValues(float[] values)
    

    数值计算

    mapPoints

    计算一组点基于当前Matrix变换后的位置,(由于是计算点,所以参数中的float数组长度一般都是偶数的,若为奇数,则最后一个数值不参与计算)。

    void mapPoints(float[] pts)
    void mapPoints(float[] dst, float[] src)
    void mapPoints(float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)
    

    方法一

    void mapPoints (float[] pts) 方法仅有一个参数,pts数组作为参数传递原始数值,计算结果仍存放在pts中。

    方法二

    void mapPoints (float[] dst, float[] src)src作为参数传递原始数值,计算结果存放在dst中,src不变。

    方法三

    void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) 可以指定只计算一部分数值。

    参数 摘要
    dst 目标数据
    dstIndex 目标数据存储位置起始下标
    src 源数据
    srcIndex 源数据存储位置起始下标
    pointCount 计算的点个数

    mapRadius

    测量半径,由于圆可能会因为画布变换变成椭圆,所以此处测量的是平均半径。

    方法

    float mapRadius(float radius)
    

    示例

    float radius = 100;
    float result = 0;
    
    // 构造一个matrix,x坐标缩放0.5
    Matrix matrix = new Matrix();
    matrix.setScale(0.5f, 1f);
    Log.i(TAG, "mapRadius: "+radius);
    result = matrix.mapRadius(radius);
    Log.i(TAG, "mapRadius: "+result);
    
    mapRadius: 100.0
    mapRadius: 70.71068
    

    mapRect

    测量矩形变换后位置,返回值是判断矩形经过变换后是否仍为矩形,非90度倍数的旋转也会变成非矩形。

    boolean mapRect(RectF rect)
    boolean mapRect(RectF dst, RectF src)
    

    方法一

    boolean mapRect (RectF rect) 测量rect并将测量结果放入rect中。

    方法二

    boolean mapRect (RectF dst, RectF src) 测量src并将测量结果放入dst中。

    mapVectors

    测量向量,mapVectorsmapPoints 基本上是相同的,可以直接参照上面的mapPoints使用方法。两者唯一的区别就是mapVectors不会受到位移的影响,这符合向量的定律。

    void mapVectors(float[] vecs)
    void mapVectors(float[] dst, float[] src)
    void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)
    

    set、pre 与 post

    方法 简介
    set 设置,会覆盖掉之前的数值,导致之前的操作失效。
    pre 前乘,构造矩阵乘式时,往前端压入乘式因子。
    post 后乘,构造矩阵乘式时,往后端压入乘式因子。

    特殊方法

    setPolyToPoly

    简介

    Poly 全称是 Polygon ,多边形的意思。setPolyToPoly()最多可以支持4个点。

    boolean setPolyToPoly (
            float[] src,    // 原始数组 src [x,y],存储内容为一组点
            int srcIndex,   // 原始数组开始位置
            float[] dst,    // 目标数组 dst [x,y],存储内容为一组点
            int dstIndex,   // 目标数组开始位置
            int pointCount) // 测控点的数量 取值范围是: 0到4
    
    pointCount 摘要
    0 相当于reset
    1 可以进行 平移
    2 可以进行 缩放、旋转、平移 变换
    3 可以进行 缩放、旋转、平移、错切 变换
    4 可以进行 缩放、旋转、平移、错切以及任何形变

    示例

    public class MatrixSetPolyToPolyTest extends View {
    
        private Bitmap mBitmap;             // 要绘制的图片
        private Matrix mPolyMatrix;         // 测试setPolyToPoly用的Matrix
    
        public MatrixSetPolyToPolyTest(Context context) {
            super(context);
    
            initBitmapAndMatrix();
        }
    
        private void initBitmapAndMatrix() {
            mBitmap = BitmapFactory.decodeResource(getResources(),
                    R.drawable.poly_test);
    
            mPolyMatrix = new Matrix();
    
    
            float[] src = {0, 0,                                    // 左上
                    mBitmap.getWidth(), 0,                          // 右上
                    mBitmap.getWidth(), mBitmap.getHeight(),        // 右下
                    0, mBitmap.getHeight()};                        // 左下
    
            float[] dst = {0, 0,                                    // 左上
                    mBitmap.getWidth(), 400,                        // 右上
                    mBitmap.getWidth(), mBitmap.getHeight() - 200,  // 右下
                    0, mBitmap.getHeight()};                        // 左下
    
            // 核心要点
            mPolyMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); // src.length >> 1 为位移运算 相当于处以2
    
            // 此处为了更好的显示对图片进行了等比缩放和平移(图片本身有点大)
            mPolyMatrix.postScale(0.26f, 0.26f);
            mPolyMatrix.postTranslate(0,200);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            // 根据Matrix绘制一个变换后的图片
            canvas.drawBitmap(mBitmap, mPolyMatrix, null);
        }
    }
    

    pointCount为0

    pointCount()0reset()是等价的。

    pointCount为1

    pointCount()1translate是等价的,平移的距离是dst - src

    pointCount为2

    pointCount2的时候,可以做缩放、平移和旋转。

    pointCount为3

    pointCount3的时候,可以做缩放、平移、旋转和错切。

    pointCount为4

    pointCount4的时候,你可以将图像拉伸为任意四边形。

    setRectToRect

    简介

    将源矩形的内容填充到目标矩形中。

    boolean setRectToRect (RectF src,           // 源区域
                    RectF dst,                  // 目标区域
                    Matrix.ScaleToFit stf)      // 缩放适配模式
    

    Matrix.ScaleToFit

    模式 摘要
    CENTER 居中,对src等比例缩放,将其居中放置在dst中。
    START 顶部,对src等比例缩放,将其放置在dst的左上角。
    END 底部,对src等比例缩放,将其放置在dst的右下角。
    FILL 充满,拉伸src的宽和高,使其完全填充满dst。

    图示

    src(原始状态)
    CENTER
    START
    END
    FILL

    示例

    展示居中例子:

    public class MatrixSetRectToRectTest extends View {
        private static final String TAG = "MatrixSetRectToRectTest";
    
        private int mViewWidth, mViewHeight;
    
        private Bitmap mBitmap;             // 要绘制的图片
        private Matrix mRectMatrix;         // 测试etRectToRect用的Matrix
    
        public MatrixSetRectToRectTest(Context context) {
            super(context);
    
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rect_test);
            mRectMatrix = new Matrix();
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mViewWidth = w;
            mViewHeight = h;
    
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            RectF src= new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight() );
            RectF dst = new RectF(0, 0, mViewWidth, mViewHeight );
    
            // 核心要点
            mRectMatrix.setRectToRect(src,dst, Matrix.ScaleToFit.CENTER);
    
            // 根据Matrix绘制一个变换后的图片
            canvas.drawBitmap(mBitmap, mRectMatrix, new Paint());
        }
    }
    

    rectStaysRect

    判断矩形经过变换后是否仍为矩形,假如Matrix进行了平移、缩放则画布仅仅是位置和大小改变,矩形变换后仍然为矩形,但Matrix进行了非90度倍数的旋转或者错切,则矩形变换后就不再是矩形了。

    setSinCos

    简介

    设置sinCos值,这个是控制Matrix旋转的,由于Matrix已经封装好了Rotate方法,所以这个并不常用。

    // 方法一
    void setSinCos (float sinValue,     // 旋转角度的sin值
                    float cosValue)     // 旋转角度的cos值
    
    // 方法二
    void setSinCos (float sinValue,     // 旋转角度的sin值
                    float cosValue,     // 旋转角度的cos值
                    float px,           // 中心位置x坐标
                    float py)           // 中心位置y坐标
    

    示例

    Matrix matrix = new Matrix();
    // 旋转90度
    // sin90=1
    // cos90=0
    matrix.setSinCos(1f, 0f);
    Log.i(TAG, "setSinCos:"+matrix.toShortString());
    // 重置
    matrix.reset();
    // 旋转90度
    matrix.setRotate(90);
    Log.i(TAG, "setRotate:"+matrix.toShortString());
    
    setSinCos:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0]
    setRotate:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0]
    

    矩阵相关

    方法 摘要
    invert 求矩阵的逆矩阵
    isAffine 判断当前矩阵是否为仿射矩阵,API21(5.0)才添加的方法。
    isIdentity 判断当前矩阵是否为单位矩阵。

    invert

    求矩阵的逆矩阵,简而言之就是计算与之前相反的矩阵,如果之前是平移200px,则求的矩阵为反向平移200px,如果之前是缩小到0.5f,则结果是放大到2倍。

    boolean invert(Matrix inverse)
    

    isAffine

    判断是否是仿射矩阵最重要的一点就是,直线是否仍为直线,简单想一下就知道,不论平移,旋转,错切,缩放,直线变换后最终仍为直线,要想让isAffine()的结果变为false,除非你能把直线掰弯。

    boolean isAffine()
    

    isIdentity

    判断是否为单位矩阵。

    实用技巧

    获取View在屏幕上的绝对位置。

    @Override
    protected void onDraw(Canvas canvas) {
        // 方式一:
        float[] values = new float[9];
        int[] location1 = new int[2];
        Matrix matrix = canvas.getMatrix();
        matrix.getValues(values);
        location1[0] = (int) values[2];
        location1[1] = (int) values[5];
        Log.i(TAG, "location1 = " + Arrays.toString(location1));
    
        // 方式二:
        int[] location2 = new int[2];
        this.getLocationOnScreen(location2);
        Log.i(TAG, "location2 = " + Arrays.toString(location2));
    }
    
    location1 = [0, 243]
    location2 = [0, 243]
    

    利用setPolyToPoly制造3D效果

    Android FoldingLayout 折叠布局 原理及实现(一)
    Android FoldingLayout 折叠布局 原理及实现(二)

    相关文章

      网友评论

          本文标题:★60.自定义控件 ★15.Matrix详解

          本文链接:https://www.haomeiwen.com/subject/sripcxtx.html