构造方法
构造方法没有在上面表格中列出。
无参构造
Matrix()
创建一个全新的Matrix,使用格式如下:
Matrix matrix = new Matrix();
通过这种方式创建出来的并不是一个数值全部为空的矩阵,而是一个单位矩阵,如下:
有参构造
Matrix (Matrix src)
这种方法则需要一个已经存在的矩阵作为参数,使用格式如下:
Matrix matrix = new Matrix(src);
创建一个Matrix,并对src深拷贝(理解为新的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]
数值操作
数值操作这一组方法可以帮助我们直接控制Matrix里面的数值。
1.set
void set (Matrix src)
没有返回值,有一个参数,作用是将参数Matrix的数值复制到当前Matrix中。如果参数为空,则重置当前Matrix,相当于reset()
。
2.reset
void reset ()
重置当前Matrix(将当前Matrix重置为单位矩阵)。
3.setValues
void setValues (float[] values)
setValues的参数是浮点型的一维数组,长度需要大于9,拷贝数组中的前9位数值赋值给当前Matrix。
4.getValues
void getValues (float[] values)
很显然,getValues和setValues是一对方法,参数也是浮点型的一维数组,长度需要大于9,将Matrix中的数值拷贝进参数的前9位中。
数值计算
1.mapPoints
void mapPoints (float[] pts)
void mapPoints (float[] dst, float[] src)
void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)
计算一组点基于当前Matrix变换后的位置,(由于是计算点,所以参数中的float数组长度一般都是偶数的,若为奇数,则最后一个数值不参与计算)。
它有三个重载方法:
(1) void mapPoints (float[] pts)
方法仅有一个参数,pts数组作为参数传递原始数值,计算结果仍存放在pts中。
(2) void mapPoints (float[] dst, float[] src)
,src作为参数传递原始数值,计算结果存放在dst中,src不变。
如果原始数据需要保留则一般使用这种方法。
(3) void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)
可以指定只计算一部分数值。
2.mapRadius
float mapRadius (float radius)
测量半径,由于圆可能会因为画布变换变成椭圆,所以此处测量的是平均半径。
测量矩形变换后位置。
(1) boolean mapRect (RectF rect)
测量rect并将测量结果放入rect中,返回值是判断矩形经过变换后是否仍为矩形。
(2) boolean mapRect (RectF dst, RectF src)
测量src并将测量结果放入dst中,返回值是判断矩形经过变换后是否仍为矩形,和之前没有什么太大区别,此处就不啰嗦了。
4.mapVectors
测量向量。
void mapVectors (float[] vecs)
void mapVectors (float[] dst, float[] src)
void mapVectors (float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)
mapVectors
与 mapPoints
基本上是相同的,可以直接参照上面的mapPoints
使用方法。
而两者唯一的区别就是mapVectors
不会受到位移的影响,这符合向量的定律,
set、pre 与 post
对于四种基本变换 平移(translate)、缩放(scale)、旋转(rotate)、 错切(skew) 它们每一种都三种操作方法,分别为 设置(set)、 前乘(pre) 和 后乘 (post)。而它们的基础是Concat,通过先构造出特殊矩阵然后用原始矩阵Concat特殊矩阵,达到变换的结果。
Matrix 相关的重要知识:
- 1.一开始从Canvas中获取到到Matrix并不是初始矩阵,而是经过偏移后到矩阵,且偏移距离就是距离屏幕左上角的位置。这个可以用于判定View在屏幕上的绝对位置,View可以根据所处位置做出调整。
- 2.构造Matrix时使用的是矩阵乘法,前乘(pre)与后乘(post)结果差别很大。这个直接参见上一篇章节 Matrix原理 即可。
- 3.受矩阵乘法影响,后面的执行的操作可能会影响到之前的操作。使用时需要注意构造顺序。
特殊方法
这一类方法看似不起眼,但拿来稍微加工一下就可能制作意想不到的效果。
1.setPolyToPoly
Poly全称是Polygon,多边形的意思,了解了意思大致就能知道这个方法是做什么用的了,应该与PS中自由变换中的扭曲有点类似。
动态效果,可以用鼠标拖动拉伸
从参数我们可以了解到setPolyToPoly最多可以支持4个点,这四个点通常为图形的四个角,可以通过这四个角将视图从矩形变换成其他形状。
从上表我们可以观察出一个规律, 随着pointCount数值增大setPolyToPoly的可以操作性也越来越强,可调整点数多了能干的事情自然也多了。
为什么说前面几种情况在实际开发中很少出现?
作为开发人员,写出来的代码出了要让机器”看懂”,没有歧义之外,最重要的还是让人看懂,以方便后期的维护修改,从上边的表格中可以看出,前面的几种种情况都可以有更直观的替代方法,只有四个参数的情况下的特殊形变是没有替代方法的。
测控点选取位置?
测控点可以选择任何你认为方便的位置,只要src与dst一一对应即可。不过为了方便,通常会选择一些特殊的点: 图形的四个角,边线的中心点以及图形的中心点等。不过有一点需要注意,测控点选取都应当是不重复的(src与dst均是如此),如果选取了重复的点会直接导致测量失效,这也意味着,你不允许将一个方形(四个点)映射为三角形(四个点,但其中两个位置重叠),但可以接近于三角形。。
作用范围?
作用范围当然是设置了Matrix的全部区域,如果你将这个Matrix赋值给了Canvas,它的作用范围就是整个画布,如果你赋值给了Bitmap,它的作用范围就是整张图片。
接下来用示例演示一下,所有示例的src均为图片大小,dst根据手势变化。
pointCount为0
pointCount为0和reset是等价的,而不是保持matrix不变,在最底层的实现中可以看到这样的代码:
if (0 == count) { this->reset(); return true; }
pointCount为1
pointCount为0和translate
是等价的
平移的距离是dst - src.
当测控点为1的时候,由于你只有一个点可以控制,所以你只能拖拽着它在2D平面上滑动。
可以拖着这个点滑动图片
pointCount为2
当pointCount为2的时候,可以做缩放、平移和旋转。
pointCount为3
当pointCount为3的时候,可以做缩放、平移、旋转和错切。
pointCount为4
当pointCount为4的时候,你可以将图像拉伸为任意四边形。
上面已经用图例比较详细的展示了不同操控点个数的情况,如果你依旧存在疑问,可以获取代码自己试一下。
2.setRectToRect
boolean setRectToRect (RectF src,
// 源区域
RectF dst,
// 目标区域
Matrix.ScaleToFit stf)
// 缩放适配模式
简单来说就是将源矩形的内容填充到目标矩形中,然而在大多数的情况下,源矩形和目标矩形的长宽比是不一致的,到底该如何填充呢,这个填充的模式就由第三个参数 stf 来确定。
ScaleToFit 是一个枚举类型,共包含了四种模式:
下面看一下不同宽高比的src与dst在不同模式下是怎样的。
假设灰色部分是dst,橙色部分是src,由于是测试不同宽高比,示例中让dst保持不变,看两种宽高比的src在不同模式下填充的位置。
3.rectStaysRect
判断矩形经过变换后是否仍为矩形,假如Matrix进行了平移、缩放则画布仅仅是位置和大小改变,矩形变换后仍然为矩形,但Matrix进行了非90度倍数的旋转或者错切,则矩形变换后就不再是矩形了,这个很好理解,不过多赘述,顺便说一下,前面的mapRect方法的返回值就是根据rectStaysRect来判断的。
4.setSinCos
设置sinCos值,这个是控制Matrix旋转的,由于Matrix已经封装好了Rotate方法,所以这个并不常用,在此仅作概述。
矩阵相关
1.invert
求矩阵的逆矩阵,简而言之就是计算与之前相反的矩阵,如果之前是平移200px,则求的矩阵为反向平移200px,如果之前是缩小到0.5f,则结果是放大到2倍。
2.isAffine
判断矩阵是否是仿射矩阵, 并没有太大用,因为你无论如何操作结果始终都为true。
因为迄今为止我们使用的所有变换都是仿射变换。
判断是否是仿射矩阵最重要的一点就是,直线是否仍为直线,简单想一下就知道,不论平移,旋转,错切,缩放,直线变换后最终仍为直线
3.isIdentity
判断是否为单位矩阵
博文链接: