Android中图像变换Matrix的原理应用,掌握了这些Android高级工程师必备知识

  1. {

  2. private Bitmap bitmap;

  3. private Matrix matrix;

  4. public TransformMatrixView(Context context)

  5. {

  6. super(context);

  7. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);

  8. matrix = new Matrix();

  9. }

  10. @Override

  11. protected void onDraw(Canvas canvas)

  12. {

  13. // 画出原图像

  14. canvas.drawBitmap(bitmap, 0, 0, null);

  15. // 画出变换后的图像

  16. canvas.drawBitmap(bitmap, matrix, null);

  17. super.onDraw(canvas);

  18. }

  19. @Override

  20. public void setImageMatrix(Matrix matrix)

  21. {

  22. this.matrix.set(matrix);

  23. super.setImageMatrix(matrix);

  24. }

  25. public Bitmap getImageBitmap()

  26. {

  27. return bitmap;

  28. }

  29. }

  30. public boolean onTouch(View v, MotionEvent e)

  31. {

  32. if(e.getAction() == MotionEvent.ACTION_UP)

  33. {

  34. Matrix matrix = new Matrix();

  35. // 输出图像的宽度和高度(162 x 251)

  36. Log.e(“TestTransformMatrixActivity”, "image size: width x height = " +  view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight());

  37. // 1. 平移

  38. matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());

  39. // 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight()

  40. view.setImageMatrix(matrix);

  41. // 下面的代码是为了查看matrix中的元素

  42. float[] matrixValues = new float[9];

  43. matrix.getValues(matrixValues);

  44. for(int i = 0; i < 3; ++i)

  45. {

  46. String temp = new String();

  47. for(int j = 0; j < 3; ++j)

  48. {

  49. temp += matrixValues[3 * i + j ] + “\t”;

  50. }

  51. Log.e(“TestTransformMatrixActivity”, temp);

  52. }

  53. //          // 2. 旋转(围绕图像的中心点)

  54. //          matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);

  55. //

  56. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  57. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 1.5f, 0f);

  58. //          view.setImageMatrix(matrix);

  59. //

  60. //          // 下面的代码是为了查看matrix中的元素

  61. //          float[] matrixValues = new float[9];

  62. //          matrix.getValues(matrixValues);

  63. //          for(int i = 0; i < 3; ++i)

  64. //          {

  65. //              String temp = new String();

  66. //              for(int j = 0; j < 3; ++j)

  67. //              {

  68. //                  temp += matrixValues[3 * i + j ] + “\t”;

  69. //              }

  70. //              Log.e(“TestTransformMatrixActivity”, temp);

  71. //          }

  72. //          // 3. 旋转(围绕坐标原点) + 平移(效果同2)

  73. //          matrix.setRotate(45f);

  74. //          matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f);

  75. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f);

  76. //

  77. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  78. //          matrix.postTranslate((float)view.getImageBitmap().getWidth() * 1.5f, 0f);

  79. //          view.setImageMatrix(matrix);

  80. //

  81. //          // 下面的代码是为了查看matrix中的元素

  82. //          float[] matrixValues = new float[9];

  83. //          matrix.getValues(matrixValues);

  84. //          for(int i = 0; i < 3; ++i)

  85. //          {

  86. //              String temp = new String();

  87. //              for(int j = 0; j < 3; ++j)

  88. //              {

  89. //                  temp += matrixValues[3 * i + j ] + “\t”;

  90. //              }

  91. //              Log.e(“TestTransformMatrixActivity”, temp);

  92. //          }

  93. //          // 4. 缩放

  94. //          matrix.setScale(2f, 2f);

  95. //          // 下面的代码是为了查看matrix中的元素

  96. //          float[] matrixValues = new float[9];

  97. //          matrix.getValues(matrixValues);

  98. //          for(int i = 0; i < 3; ++i)

  99. //          {

  100. //              String temp = new String();

  101. //              for(int j = 0; j < 3; ++j)

  102. //              {

  103. //                  temp += matrixValues[3 * i + j ] + “\t”;

  104. //              }

  105. //              Log.e(“TestTransformMatrixActivity”, temp);

  106. //          }

  107. //

  108. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  109. //          matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());

  110. //          view.setImageMatrix(matrix);

  111. //

  112. //          // 下面的代码是为了查看matrix中的元素

  113. //          matrixValues = new float[9];

  114. //          matrix.getValues(matrixValues);

  115. //          for(int i = 0; i < 3; ++i)

  116. //          {

  117. //              String temp = new String();

  118. //              for(int j = 0; j < 3; ++j)

  119. //              {

  120. //                  temp += matrixValues[3 * i + j ] + “\t”;

  121. //              }

  122. //              Log.e(“TestTransformMatrixActivity”, temp);

  123. //          }

  124. //          // 5. 错切 - 水平

  125. //          matrix.setSkew(0.5f, 0f);

  126. //          // 下面的代码是为了查看matrix中的元素

  127. //          float[] matrixValues = new float[9];

  128. //          matrix.getValues(matrixValues);

  129. //          for(int i = 0; i < 3; ++i)

  130. //          {

  131. //              String temp = new String();

  132. //              for(int j = 0; j < 3; ++j)

  133. //              {

  134. //                  temp += matrixValues[3 * i + j ] + “\t”;

  135. //              }

  136. //              Log.e(“TestTransformMatrixActivity”, temp);

  137. //          }

  138. //

  139. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  140. //          matrix.postTranslate(view.getImageBitmap().getWidth(), 0f);

  141. //          view.setImageMatrix(matrix);

  142. //

  143. //          // 下面的代码是为了查看matrix中的元素

  144. //          matrixValues = new float[9];

  145. //          matrix.getValues(matrixValues);

  146. //          for(int i = 0; i < 3; ++i)

  147. //          {

  148. //              String temp = new String();

  149. //              for(int j = 0; j < 3; ++j)

  150. //              {

  151. //                  temp += matrixValues[3 * i + j ] + “\t”;

  152. //              }

  153. //              Log.e(“TestTransformMatrixActivity”, temp);

  154. //          }

  155. //          // 6. 错切 - 垂直

  156. //          matrix.setSkew(0f, 0.5f);

  157. //          // 下面的代码是为了查看matrix中的元素

  158. //          float[] matrixValues = new float[9];

  159. //          matrix.getValues(matrixValues);

  160. //          for(int i = 0; i < 3; ++i)

  161. //          {

  162. //              String temp = new String();

  163. //              for(int j = 0; j < 3; ++j)

  164. //              {

  165. //                  temp += matrixValues[3 * i + j ] + “\t”;

  166. //              }

  167. //              Log.e(“TestTransformMatrixActivity”, temp);

  168. //          }

  169. //

  170. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  171. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());

  172. //          view.setImageMatrix(matrix);

  173. //

  174. //          // 下面的代码是为了查看matrix中的元素

  175. //          matrixValues = new float[9];

  176. //          matrix.getValues(matrixValues);

  177. //          for(int i = 0; i < 3; ++i)

  178. //          {

  179. //              String temp = new String();

  180. //              for(int j = 0; j < 3; ++j)

  181. //              {

  182. //                  temp += matrixValues[3 * i + j ] + “\t”;

  183. //              }

  184. //              Log.e(“TestTransformMatrixActivity”, temp);

  185. //          }

  186. //          7. 错切 - 水平 + 垂直

  187. //          matrix.setSkew(0.5f, 0.5f);

  188. //          // 下面的代码是为了查看matrix中的元素

  189. //          float[] matrixValues = new float[9];

  190. //          matrix.getValues(matrixValues);

  191. //          for(int i = 0; i < 3; ++i)

  192. //          {

  193. //              String temp = new String();

  194. //              for(int j = 0; j < 3; ++j)

  195. //              {

  196. //                  temp += matrixValues[3 * i + j ] + “\t”;

  197. //              }

  198. //              Log.e(“TestTransformMatrixActivity”, temp);

  199. //          }

  200. //

  201. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  202. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());

  203. //          view.setImageMatrix(matrix);

  204. //

  205. //          // 下面的代码是为了查看matrix中的元素

  206. //          matrixValues = new float[9];

  207. //          matrix.getValues(matrixValues);

  208. //          for(int i = 0; i < 3; ++i)

  209. //          {

  210. //              String temp = new String();

  211. //              for(int j = 0; j < 3; ++j)

  212. //              {

  213. //                  temp += matrixValues[3 * i + j ] + “\t”;

  214. //              }

  215. //              Log.e(“TestTransformMatrixActivity”, temp);

  216. //          }

  217. //          // 8. 对称 (水平对称)

  218. //          float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};

  219. //          matrix.setValues(matrix_values);

  220. //          // 下面的代码是为了查看matrix中的元素

  221. //          float[] matrixValues = new float[9];

  222. //          matrix.getValues(matrixValues);

  223. //          for(int i = 0; i < 3; ++i)

  224. //          {

  225. //              String temp = new String();

  226. //              for(int j = 0; j < 3; ++j)

  227. //              {

  228. //                  temp += matrixValues[3 * i + j ] + “\t”;

  229. //              }

  230. //              Log.e(“TestTransformMatrixActivity”, temp);

  231. //          }

  232. //

  233. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  234. //          matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f);

  235. //          view.setImageMatrix(matrix);

  236. //

  237. //          // 下面的代码是为了查看matrix中的元素

  238. //          matrixValues = new float[9];

  239. //          matrix.getValues(matrixValues);

  240. //          for(int i = 0; i < 3; ++i)

  241. //          {

  242. //              String temp = new String();

  243. //              for(int j = 0; j < 3; ++j)

  244. //              {

  245. //                  temp += matrixValues[3 * i + j ] + “\t”;

  246. //              }

  247. //              Log.e(“TestTransformMatrixActivity”, temp);

  248. //          }

  249. //          // 9. 对称 - 垂直

  250. //          float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};

  251. //          matrix.setValues(matrix_values);

  252. //          // 下面的代码是为了查看matrix中的元素

  253. //          float[] matrixValues = new float[9];

  254. //          matrix.getValues(matrixValues);

  255. //          for(int i = 0; i < 3; ++i)

  256. //          {

  257. //              String temp = new String();

  258. //              for(int j = 0; j < 3; ++j)

  259. //              {

  260. //                  temp += matrixValues[3 * i + j ] + “\t”;

  261. //              }

  262. //              Log.e(“TestTransformMatrixActivity”, temp);

  263. //          }

  264. //

  265. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  266. //          matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f);

  267. //          view.setImageMatrix(matrix);

  268. //

  269. //          // 下面的代码是为了查看matrix中的元素

  270. //          matrixValues = new float[9];

  271. //          matrix.getValues(matrixValues);

  272. //          for(int i = 0; i < 3; ++i)

  273. //          {

  274. //              String temp = new String();

  275. //              for(int j = 0; j < 3; ++j)

  276. //              {

  277. //                  temp += matrixValues[3 * i + j ] + “\t”;

  278. //              }

  279. //              Log.e(“TestTransformMatrixActivity”, temp);

  280. //          }

  281. //          // 10. 对称(对称轴为直线y = x)

  282. //          float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};

  283. //          matrix.setValues(matrix_values);

  284. //          // 下面的代码是为了查看matrix中的元素

  285. //          float[] matrixValues = new float[9];

  286. //          matrix.getValues(matrixValues);

  287. //          for(int i = 0; i < 3; ++i)

  288. //          {

  289. //              String temp = new String();

  290. //              for(int j = 0; j < 3; ++j)

  291. //              {

  292. //                  temp += matrixValues[3 * i + j ] + “\t”;

  293. //              }

  294. //              Log.e(“TestTransformMatrixActivity”, temp);

  295. //          }

  296. //

  297. //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠

  298. //          matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(),

  299. //                  view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth());

  300. //          view.setImageMatrix(matrix);

  301. //

  302. //          // 下面的代码是为了查看matrix中的元素

  303. //          matrixValues = new float[9];

  304. //          matrix.getValues(matrixValues);

  305. //          for(int i = 0; i < 3; ++i)

  306. //          {

  307. //              String temp = new String();

  308. //              for(int j = 0; j < 3; ++j)

  309. //              {

  310. //                  temp += matrixValues[3 * i + j ] + “\t”;

  311. //              }

  312. //              Log.e(“TestTransformMatrixActivity”, temp);

  313. //          }

  314. view.invalidate();

  315. }

  316. return true;

  317. }

  318. }


  319.   

第三部分 应用

在这一部分,我们会将前面两部分所了解到的内容和Android手势结合起来,利用各种不同的手势对图像进行平移、缩放和旋转,前面两项都是在实践中经常需要用到的功能,后一项据说苹果也是最近才加上的,而实际上在Android中,咱们通过自己的双手,也可以很轻松地实现之。

首先创建一个Android项目PatImageView,同时创建一个Activity:PatImageViewActivity。完成这一步后, 记得在AndroidManifest.xml中增加如下许可:

uses-permissionandroid:name=_“android.permission.VIBRATE”_/

因为我们将要通过短按还是长按,来确定将图片到底是缩放还是旋转。

现在来创建一个ImageView的派生类:PatImageView,其代码(PatImageView.java)如下(2011-11-22 revised):

[java]  view plain copy

  1. package com.pat.imageview;

  2. import android.app.Service;

  3. import android.content.Context;

  4. import android.graphics.Matrix;

  5. import android.graphics.PointF;

  6. import android.os.Vibrator;

  7. import android.util.FloatMath;

  8. import android.view.GestureDetector;

  9. import android.view.MotionEvent;

  10. import android.view.View;

  11. import android.widget.ImageView;

  12. public class PatImageView extends ImageView

  13. {

  14. private Matrix matrix;

  15. private Matrix savedMatrix;

  16. private boolean long_touch = false;

  17. private static int NONE = 0;

  18. private static int DRAG = 1;    // 拖动

  19. private static int ZOOM = 2;    // 缩放

  20. private static int ROTA = 3;    // 旋转

  21. private int mode = NONE;

  22. private PointF startPoint;

  23. private PointF middlePoint;

  24. private float oldDistance;

  25. private float oldAngle;

  26. private Vibrator vibrator;

  27. private GestureDetector gdetector;

  28. public PatImageView(final Context context)

  29. {

  30. super(context);

  31. matrix = new Matrix();

  32. savedMatrix = new Matrix();

  33. matrix.setTranslate(0f, 0f);

  34. setScaleType(ScaleType.MATRIX);

  35. setImageMatrix(matrix);

  36. startPoint = new PointF();

  37. middlePoint = new PointF();

  38. oldDistance = 1f;

  39. gdetector = new GestureDetector(context, new GestureDetector.OnGestureListener()

  40. {

  41. @Override

  42. public boolean onSingleTapUp(MotionEvent e)

  43. {

  44. return true;

  45. }

  46. @Override

  47. public void onShowPress(MotionEvent e)

  48. {

  49. }

  50. @Override

  51. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

  52. {

  53. return true;

  54. }

  55. @Override

  56. public void onLongPress(MotionEvent e)

  57. {

  58. long_touch = true;

  59. vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);

  60. // 振动50ms,提示后续的操作将是旋转图片,而非缩放图片

  61. vibrator.vibrate(50);

  62. }

  63. @Override

  64. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

  65. {

  66. return true;

  67. }

  68. @Override

  69. public boolean onDown(MotionEvent e)

  70. {

  71. return true;

  72. }

  73. });

  74. setOnTouchListener(new OnTouchListener()

  75. {

  76. public boolean onTouch(View view, MotionEvent event)

  77. {

  78. switch(event.getAction() & MotionEvent.ACTION_MASK)

  79. {

  80. case MotionEvent.ACTION_DOWN:           // 第一个手指touch

  81. savedMatrix.set(matrix);

  82. startPoint.set(event.getX(), event.getY());

  83. mode = DRAG;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

尾声

如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

这里,笔者分享一份从架构哲学的层面来剖析的视频及资料给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

Android进阶学习资料库

一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

《2019-2021字节跳动Android面试历年真题解析》

3663097)]
[外链图片转存中…(img-Wss08e3b-1711913663097)]
[外链图片转存中…(img-zS3w9o1F-1711913663097)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-lGR1ATM1-1711913663098)]

尾声

如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

这里,笔者分享一份从架构哲学的层面来剖析的视频及资料给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

[外链图片转存中…(img-ZZH21Z1l-1711913663098)]

Android进阶学习资料库

一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!

[外链图片转存中…(img-xZRI6Xjv-1711913663098)]

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-fZAVmLVp-1711913663098)]

《2019-2021字节跳动Android面试历年真题解析》

[外链图片转存中…(img-2fJ4PCca-1711913663099)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值