|
18 | 18 | | 前乘(pre) | preConcat preRotate preScale preSkew preTranslate | 前乘变换 | |
19 | 19 | | 后乘(post) | postConcat postRotate postScale postSkew postTranslate | 后乘变换 | |
20 | 20 | | 特殊方法 | setPolyToPoly setRectToRect rectStaysRect setSinCos | 一些特殊操作 | |
21 | | -| 矩阵相关 | invert isAffine isIdentity | 求逆矩阵、 是否为仿射矩阵、 是否为单位矩阵 ... | |
| 21 | +| 矩阵相关 | invert isAffine(API21) isIdentity | 求逆矩阵、 是否为仿射矩阵、 是否为单位矩阵 ... | |
22 | 22 |
|
23 | 23 |
|
24 | 24 | ## Matrix方法详解 |
@@ -371,7 +371,7 @@ mapPoints: [600.0, 900.0] |
371 | 371 |
|
372 | 372 | ### set、pre 与 post |
373 | 373 |
|
374 | | -对于四种基本变换 平移(translate)、缩放(scale)、旋转(rotate)、 错切(skew) 它们每一种都三种操作方法,分别为 设置(set)、 前乘(pre) 和 后乘 (post)。 |
| 374 | +对于四种基本变换 平移(translate)、缩放(scale)、旋转(rotate)、 错切(skew) 它们每一种都三种操作方法,分别为 设置(set)、 前乘(pre) 和 后乘 (post)。而它们的基础是Concat,通过先构造出特殊矩阵然后用原始矩阵Concat特殊矩阵,达到变换的结果。 |
375 | 375 |
|
376 | 376 | **关于四种基本变换的知识和三种对应操作的区别,详细可以参考 [Canvas之画布操作](http://www.gcssloop.com/2015/02/Canvas_Convert/) 和 [Matrix原理](http://www.gcssloop.com/2015/02/Matrix_Basic/) 这两篇文章的内容。** |
377 | 377 |
|
@@ -557,30 +557,238 @@ public class MatrixSetRectToRectTest extends View { |
557 | 557 |
|
558 | 558 | **3.rectStaysRect** |
559 | 559 |
|
560 | | -判断矩形经过变换后是否仍为矩形,假如Matrix进行了平移、缩放则画布仅仅是位置和大小改变,矩形变换后仍然为矩形,但Matrix进行了非90度倍数的旋转或者错切,则矩形变换后就不再是矩形了,这个很好理解,不过多赘述,顺便说一下,前面的`mapRect`方法的返回值就是`rectStaysRect`的返回值。 |
| 560 | +判断矩形经过变换后是否仍为矩形,假如Matrix进行了平移、缩放则画布仅仅是位置和大小改变,矩形变换后仍然为矩形,但Matrix进行了非90度倍数的旋转或者错切,则矩形变换后就不再是矩形了,这个很好理解,不过多赘述,顺便说一下,前面的`mapRect`方法的返回值就是根据`rectStaysRect`来判断的。 |
561 | 561 |
|
562 | 562 |
|
563 | 563 |
|
564 | 564 | **4.setSinCos** |
565 | 565 |
|
566 | | -设置sinCos值,这个是控制Matrix旋转的,由于Matrix已经封装好了Rotate方法,所以这个并不常用,也不过多讲解。 |
| 566 | +设置sinCos值,这个是控制Matrix旋转的,由于Matrix已经封装好了Rotate方法,所以这个并不常用,在此仅作概述。 |
| 567 | +
|
| 568 | +```java |
| 569 | +// 方法一 |
| 570 | +void setSinCos (float sinValue, // 旋转角度的sin值 |
| 571 | + float cosValue) // 旋转角度的cos值 |
| 572 | +
|
| 573 | +// 方法二 |
| 574 | +void setSinCos (float sinValue, // 旋转角度的sin值 |
| 575 | + float cosValue, // 旋转角度的cos值 |
| 576 | + float px, // 中心位置x坐标 |
| 577 | + float py) // 中心位置y坐标 |
| 578 | +``` |
| 579 | +
|
| 580 | +简单测试: |
| 581 | +
|
| 582 | +```java |
| 583 | +Matrix matrix = new Matrix(); |
| 584 | +// 旋转90度 |
| 585 | +// sin90=1 |
| 586 | +// cos90=0 |
| 587 | +matrix.setSinCos(1f, 0f); |
| 588 | +
|
| 589 | +Log.i(TAG, "setSinCos:"+matrix.toShortString()); |
| 590 | +
|
| 591 | +// 重置 |
| 592 | +matrix.reset(); |
| 593 | +
|
| 594 | +// 旋转90度 |
| 595 | +matrix.setRotate(90); |
| 596 | +
|
| 597 | +Log.i(TAG, "setRotate:"+matrix.toShortString()); |
| 598 | +``` |
| 599 | +
|
| 600 | +结果: |
| 601 | +
|
| 602 | +```shell |
| 603 | +setSinCos:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0] |
| 604 | +setRotate:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0] |
| 605 | +``` |
| 606 | +
|
| 607 | +
|
567 | 608 |
|
568 | 609 | ### 矩阵相关 |
569 | 610 |
|
570 | | -矩阵相关的函数就属于哪一种非常靠近底层的东西了,向我们做App的一般不需要直接接触到这些东西,想要弄明白这个可以回去请教你们的线性代数老师,这里仅作概述。 |
| 611 | +矩阵相关的函数就属于哪一种非常靠近底层的东西了,大部分开发者很少直接接触这些东西,想要弄明白这个可以回去请教你们的线性代数老师,这里也仅作概述。 |
| 612 | +
|
| 613 | +| 方法 | 摘要 | |
| 614 | +| ---------- | ------------------------------- | |
| 615 | +| invert | 求矩阵的逆矩阵 | |
| 616 | +| isAffine | 判断当前矩阵是否为仿射矩阵,API21(5.0)才添加的方法。 | |
| 617 | +| isIdentity | 判断当前矩阵是否为单位矩阵。 | |
| 618 | +
|
| 619 | +**1.invert** |
| 620 | +
|
| 621 | +求矩阵的逆矩阵,简而言之就是计算与之前相反的矩阵,如果之前是平移200px,则求的矩阵为反向平移200px,如果之前是缩小到0.5f,则结果是放大到2倍。 |
| 622 | +
|
| 623 | +```java |
| 624 | +boolean invert (Matrix inverse) |
| 625 | +``` |
| 626 | +
|
| 627 | +简单测试: |
| 628 | +
|
| 629 | +```java |
| 630 | +Matrix matrix = new Matrix(); |
| 631 | +Matrix invert = new Matrix(); |
| 632 | +matrix.setTranslate(200,500); |
| 633 | +
|
| 634 | +Log.e(TAG, "before - matrix "+matrix.toShortString() ); |
| 635 | +
|
| 636 | +Boolean result = matrix.invert(invert); |
| 637 | +
|
| 638 | +Log.e(TAG, "after - result "+result ); |
| 639 | +Log.e(TAG, "after - matrix "+matrix.toShortString() ); |
| 640 | +Log.e(TAG, "after - invert "+invert.toShortString() ); |
| 641 | +``` |
| 642 | +
|
| 643 | +结果: |
| 644 | +
|
| 645 | +```shell |
| 646 | +before - matrix [1.0, 0.0, 200.0][0.0, 1.0, 500.0][0.0, 0.0, 1.0] |
| 647 | +after - result true |
| 648 | +after - matrix [1.0, 0.0, 200.0][0.0, 1.0, 500.0][0.0, 0.0, 1.0] |
| 649 | +after - invert [1.0, 0.0, -200.0][0.0, 1.0, -500.0][0.0, 0.0, 1.0] |
| 650 | +``` |
| 651 | +
|
| 652 | +
|
| 653 | +
|
| 654 | +**2.isAffine** |
| 655 | +
|
| 656 | +判断矩阵是否是仿射矩阵, 貌似并没有太大卵用,因为你无论如何操作结果始终都为true。 |
| 657 | +
|
| 658 | +这是为什么呢?因为迄今为止我们使用的所有变换都是仿射变换,那变换出来的矩阵自然是仿射矩阵喽。 |
| 659 | +
|
| 660 | +判断是否是仿射矩阵最重要的一点就是,直线是否仍为直线,简单想一下就知道,不论平移,旋转,错切,缩放,直线变换后最终仍为直线,要想让`isAffine`的结果变为false,除非你能把直线掰弯,我目前还没有找到能够掰弯的方法,所以我仍是直男(就算找到了,我依旧是直男)。 |
| 661 | +
|
| 662 | +简单测试: |
| 663 | +
|
| 664 | +```java |
| 665 | +Matrix matrix = new Matrix(); |
| 666 | +Log.i(TAG,"isAffine="+matrix.isAffine()); |
| 667 | +
|
| 668 | +matrix.postTranslate(200,0); |
| 669 | +matrix.postScale(0.5f, 1); |
| 670 | +matrix.postSkew(0,1); |
| 671 | +matrix.postRotate(56); |
| 672 | +
|
| 673 | +Log.i(TAG,"isAffine="+matrix.isAffine()); |
| 674 | +``` |
| 675 | +
|
| 676 | +结果: |
| 677 | +
|
| 678 | +```shell |
| 679 | +isAffine=true |
| 680 | +isAffine=true |
| 681 | +``` |
| 682 | +
|
| 683 | +
|
| 684 | +
|
| 685 | +**3.isIdentity** |
| 686 | +
|
| 687 | +判断是否为单位矩阵,什么是单位矩阵呢,就是文章一开始的那个: |
| 688 | +
|
| 689 | + |
| 698 | +
|
| 699 | +新创建的Matrix和重置后的Matrix都是单位矩阵,不过,只要随意操作一步,就不在是单位矩阵了。 |
| 700 | +
|
| 701 | +简单测试: |
| 702 | +
|
| 703 | +```java |
| 704 | +Matrix matrix = new Matrix(); |
| 705 | +Log.i(TAG,"isIdentity="+matrix.isIdentity()); |
| 706 | +
|
| 707 | +matrix.postTranslate(200,0); |
| 708 | +
|
| 709 | +Log.i(TAG,"isIdentity="+matrix.isIdentity()); |
| 710 | +``` |
| 711 | +
|
| 712 | +结果: |
| 713 | +
|
| 714 | +```shell |
| 715 | +isIdentity=true |
| 716 | +isIdentity=false |
| 717 | +``` |
| 718 | +
|
571 | 719 |
|
572 | | -| 方法 | 摘要 | |
573 | | -| ---------- | -------------- | |
574 | | -| invert | 求矩阵的逆矩阵 | |
575 | | -| isAffine | 判断当前矩阵是否为仿射矩阵。 | |
576 | | -| isIdentity | 判断当前矩阵是否为单位矩阵。 | |
577 | 720 |
|
578 | 721 | ## Matrix实用技巧 |
579 | 722 |
|
580 | | -通过前面的代码和示例,我们已经了解了Matrix大部分方法是如何使用的,这些基本的原理和方法通过组合可能会创造出神奇的东西,下面我就简要介绍几种我想到的小技巧,更多的大家可以开启自己的脑洞来发挥。 |
| 723 | +通过前面的代码和示例,我们已经了解了Matrix大部分方法是如何使用的,这些基本的原理和方法通过组合可能会创造出神奇的东西,网上有很多教程讲Bitmap利用Matrix变换来制作镜像倒影等,这都属于Matrix的基本应用,我就不在赘述了,下面我简要介绍几种然并卵的小技巧,更多的大家可以开启自己的脑洞来发挥。 |
| 724 | +
|
| 725 | +### 1.获取View在屏幕上的绝对位置 |
| 726 | +
|
| 727 | +在之前的文章[Matrix原理](http://www.gcssloop.com/2015/02/Matrix_Basic/)中我们提到过Matrix最根本的作用就是坐标映射,将View的相对坐标映射为屏幕的绝对坐标,也提到过我们在onDraw函数的canvas中获取到到Matrix并不是单位矩阵,结合这两点,聪明的你肯定想到了我们可以从canvas的Matrix入手取得View在屏幕上的绝对位置。 |
| 728 | +
|
| 729 | +不过,这也仅仅是一个然并卵的小技巧而已,使用`getLocationOnScreen`同样可以获取View在屏幕的位置,但如果你是想让下一任接盘侠弄不明白你在做什么或者是被同事打死的话,尽管这么做。 |
| 730 | +
|
| 731 | +简单示例: |
| 732 | +
|
| 733 | +```java |
| 734 | +@Override |
| 735 | +protected void onDraw(Canvas canvas) { |
| 736 | + float[] values = new float[9]; |
| 737 | + int[] location1 = new int[2]; |
| 738 | +
|
| 739 | + Matrix matrix = canvas.getMatrix(); |
| 740 | + matrix.getValues(values); |
| 741 | +
|
| 742 | + location1[0] = (int) values[2]; |
| 743 | + location1[1] = (int) values[5]; |
| 744 | + Log.i(TAG, "location1 = " + Arrays.toString(location1)); |
| 745 | +
|
| 746 | + int[] location2 = new int[2]; |
| 747 | + this.getLocationOnScreen(location2); |
| 748 | + Log.i(TAG, "location2 = " + Arrays.toString(location2)); |
| 749 | +} |
| 750 | +``` |
| 751 | +
|
| 752 | +结果: |
| 753 | +
|
| 754 | +```shell |
| 755 | +location1 = [0, 243] |
| 756 | +location2 = [0, 243] |
| 757 | +``` |
| 758 | +
|
| 759 | +### 2.利用setPolyToPoly制造3D效果 |
| 760 | +
|
| 761 | +这个全凭大家想象力啦,不过我搜了一下还真搜到了好东西,之前鸿洋大大发过一篇博文详细讲解了利用setPolyToPoly制造的折叠效果布局,大家直接到他的博客去看吧,我就不写了。 |
581 | 762 |
|
582 | | -### 1.根据位置绘制不同的内容 |
| 763 | +> 图片引用自鸿洋大大的博客,稍作了一下处理。 |
583 | 764 |
|
584 | | -## About |
| 765 | + |
| 766 | +
|
| 767 | +博文链接: |
| 768 | +
|
| 769 | +**[Android FoldingLayout 折叠布局 原理及实现(一)](http://blog.csdn.net/lmj623565791/article/details/44278417)** |
| 770 | +
|
| 771 | +**[Android FoldingLayout 折叠布局 原理及实现(二)](http://blog.csdn.net/lmj623565791/article/details/44283093)** |
| 772 | +
|
| 773 | +## 总结 |
| 774 | +
|
| 775 | +本篇基本讲解了Matrix相关的所有方法,应该是目前对Matrix讲解最全面的一篇中文文章了,建议配合上一篇[Matrix原理](http://www.gcssloop.com/2015/02/Matrix_Basic/)食用效果更佳。 |
| 776 | +
|
| 777 | +由于本人水平有限,可能出于误解或者笔误难免出错,如果发现有问题或者对文中内容存在疑问欢迎在下面评论区告诉我,请对问题描述尽量详细,以帮助我可以快速找到问题根源。 |
| 778 | +
|
| 779 | +## About Me |
| 780 | +
|
| 781 | +### 作者微博: <a href="http://weibo.com/GcsSloop" target="_blank">@GcsSloop</a> |
| 782 | +
|
| 783 | +<a href="https://github.com/GcsSloop/AndroidNote/blob/magic-world/FINDME.md" target="_blank"> <img src="http://ww4.sinaimg.cn/large/005Xtdi2gw1f1qn89ihu3j315o0dwwjc.jpg" width=300/> </a> |
585 | 784 |
|
586 | 785 | ## 参考资料 |
| 786 | +
|
| 787 | +[Matrix](https://developer.android.com/reference/android/graphics/Matrix.html) |
| 788 | +
|
| 789 | +[Matrix.ScaleToFit](https://developer.android.com/reference/android/graphics/Matrix.ScaleToFit.html) |
| 790 | +
|
| 791 | +[Android中图像变换Matrix的原理、代码验证和应用](http://biandroid.iteye.com/blog/1399462) |
| 792 | +
|
| 793 | +[Understanding Affine Transformations With Matrix Mathematics](http://code.tutsplus.com/tutorials/understanding-affine-transformations-with-matrix-mathematics--active-10884) |
| 794 | +
|
0 commit comments