第三部分 应用

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

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

<uses-permissionandroid:name="android.permission.VIBRATE"/>

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

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

  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;
  84. long_touch = false;
  85. break;
  86. case MotionEvent.ACTION_POINTER_DOWN:   // 第二个手指touch
  87. oldDistance = getDistance(event);   // 计算第二个手指touch时,两指之间的距离
  88. oldAngle = getDegree(event);        // 计算第二个手指touch时,两指所形成的直线和x轴的角度
  89. if(oldDistance > 10f)
  90. {
  91. savedMatrix.set(matrix);
  92. middlePoint = midPoint(event);
  93. if(!long_touch)
  94. {
  95. mode = ZOOM;
  96. }
  97. else
  98. {
  99. mode = ROTA;
  100. }
  101. }
  102. break;
  103. case MotionEvent.ACTION_UP:
  104. mode = NONE;
  105. break;
  106. case MotionEvent.ACTION_POINTER_UP:
  107. mode = NONE;
  108. break;
  109. case MotionEvent.ACTION_MOVE:
  110. if(vibrator != null)    vibrator.cancel();
  111. if(mode == DRAG)
  112. {
  113. matrix.set(savedMatrix);
  114. matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
  115. }
  116. if(mode == ZOOM)
  117. {
  118. float newDistance = getDistance(event);
  119. if(newDistance > 10f)
  120. {
  121. matrix.set(savedMatrix);
  122. float scale = newDistance / oldDistance;
  123. matrix.postScale(scale, scale, middlePoint.x, middlePoint.y);
  124. }
  125. }
  126. if(mode == ROTA)
  127. {
  128. float newAngle = getDegree(event);
  129. matrix.set(savedMatrix);
  130. float degrees = newAngle - oldAngle;
  131. matrix.postRotate(degrees, middlePoint.x, middlePoint.y);
  132. }
  133. break;
  134. }
  135. setImageMatrix(matrix);
  136. invalidate();
  137. gdetector.onTouchEvent(event);
  138. return true;
  139. }
  140. });
  141. }
  142. // 计算两个手指之间的距离
  143. private float getDistance(MotionEvent event)
  144. {
  145. float x = event.getX(0) - event.getX(1);
  146. float y = event.getY(0) - event.getY(1);
  147. return FloatMath.sqrt(x * x + y * y);
  148. }
  149. // 计算两个手指所形成的直线和x轴的角度
  150. private float getDegree(MotionEvent event)
  151. {
  152. return (float)(Math.atan((event.getY(1) - event.getY(0)) / (event.getX(1) - event.getX(0))) * 180f);
  153. }
  154. // 计算两个手指之间,中间点的坐标
  155. private PointF midPoint( MotionEvent event)
  156. {
  157. PointF point = new PointF();
  158. float x = event.getX(0) + event.getX(1);
  159. float y = event.getY(0) + event.getY(1);
  160. point.set(x / 2, y / 2);
  161. return point;
  162. }
  163. }

下面完善PatImageViewActivity.java的代码,使之如下:

  1. package com.pat.imageview;
  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.os.Bundle;
  6. import android.view.Window;
  7. import android.view.WindowManager;
  8. public class PatImageViewActivity extends Activity
  9. {
  10. @Override
  11. public void onCreate(Bundle savedInstanceState)
  12. {
  13. super.onCreate(savedInstanceState);
  14. requestWindowFeature(Window.FEATURE_NO_TITLE);
  15. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  16. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  17. PatImageView piv = new PatImageView(this);
  18. Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);
  19. piv.setImageBitmap(bmp);
  20. setContentView(piv);
  21. }
  22. }

由于有些手势在模拟器上无法模拟,所以就不上运行结果的图片了。本人在真机上运行后(照片就不拍了,有点累啦),可以轻松做到:

1.     很方便地拖动图片(比如,单指按住屏幕进行拖动)

2.     很方便地缩放图片(比如,双指按住屏幕进行分开或者并拢操作,可分别实现放大或者缩小图片的功能)

3.     长按出现振动后,可以很方便地旋转图片(一个手指固定,另外一个手指围绕那个固定的手指运动)。

Android中图像变换Matrix的原理、代码验证和应用(三)的更多相关文章

  1. Android中图像变换Matrix的原理、代码验证和应用(一)

    第一部分 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matri ...

  2. Android中图像变换Matrix的原理、代码验证和应用(二)

    第二部分 代码验证 在第一部分中讲到的各种图像变换的验证代码如下,一共列出了10种情况.如果要验证其中的某一种情况,只需将相应的代码反注释即可.试验中用到的图片: 其尺寸为162 x 251. 每种变 ...

  3. Android中的LruCache的原理和使用

    Android中的LruCache的原理和使用 LruCache,虽然很多文章都把LRU翻译成"最近最少使用"缓存策略,但Android中的LruCache真的如此吗? 答案是No ...

  4. Android中SensorManager.getRotationMatrix函数原理解释

    SensorManager是Android中的一个类,其有一个函数getRotationMatrix,可以计算出旋转矩阵,进而通过getOrientation求得设备的方向(航向角.俯仰角.横滚角). ...

  5. Android中的Matrix(矩阵)

    写在前面 看这篇笔记之前先看一下参考文章,这篇笔记没有系统的讲述矩阵和代码的东西,参考文章写的也有错误的地方,要辨证的看. 如何计算矩阵乘法 android matrix 最全方法详解与进阶(完整篇) ...

  6. Android 中View的工作原理

    Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...

  7. Android中微信抢红包插件原理解析和开发实现

    一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...

  8. 【转】Android 学习笔记——利用JNI技术在Android中调用、调试C++代码

    原文网址:http://cherishlc.iteye.com/blog/1756762 在Android中调用C++其实就是在Java中调用C++代码,只是在windows下编译生成DLL,在And ...

  9. Android中典型的ROOT原理(5)

    ROOT的作用 Customization 用户的个人定制,如删除一些预安装,定制开机动画等. 特权操作 所有需要特权操作的基本都是要通过ROOT,这也是ROOT的初衷. ROOT的第一步:寻找漏洞并 ...

随机推荐

  1. android studio 应用小知识总结

    1.在复制一个工程文件后 想修改包名,则在Android下的java中的 Android test中,鼠标右键Refactor->rename->Rename_package->Do ...

  2. EditText限制输入字符类型的几种方式

    最近的项目上需要限制EditText输入字符的类型,就把可以实现这个功能的方法整理了一下: 1.第一种方式是通过EditText的inputType来实现,可以通过xml或者Java文件来设置.假如我 ...

  3. two sample ttest & paired ttst

    来源:http://www.pinzhi.org/thread-1023-1-1.html 成对t检验Paired Test是对来自同一总体的样本,在不同条件影响下获取的2组样本进行分析,以评价不同条 ...

  4. Html5 Egret游戏开发 成语大挑战(四)选关界面

    通过前面的开始界面基本上了解了eui的使用方法,可以简单快速的制作一个UI界面,本篇使用第二界面选关界面展示更为难一点的代码控制,来展现关卡地图的内容,请确保素材和资源完整,可以在前面的教程中找到下载 ...

  5. Android — Camera聚焦流程

    原文  http://www.cnphp6.com/archives/65098 主题 Android Camera.java autoFocus()聚焦回调函数 @Override public v ...

  6. TinyFrame升级之一:框架概览

    由于之前的TinyFrame多于简单,并且只是说明原理,并无成型的框架出来,所以这次我把之前的知识进行了汇总,然后做出了这一版的TinyFrame框架. 整个框架的结构如下: TinyFrame.Da ...

  7. Apache Shiro 使用手册(一)Shiro架构介绍 - kdboy - ITeye技术网站

    转载 原文地址 http://kdboy.iteye.com/blog/1154644 一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理 ...

  8. web性能优化——浏览器相关

    简介 优化是一个持续的过程.所以尽可能的不要有人为的参与.所以能自动化的或者能从架构.框架级别解决的就最更高级别解决. 这样即能实现面对开发人员是透明的.不响应,又能确保所有资源都是被优化过的. 场景 ...

  9. 171 Excel Sheet Column Number

    /** * 题意:A表示1 B表示2 AA表示27 AB表示28 ------>给你一串字符串输出相应的数字 * 分析:这个就类似于二进制转十进制,从字符串后面往前遍历,然后pow(26,n)* ...

  10. 20160205 - Windows 10 家庭版没有组策略

    问题描述:买笔电自带的正版系统,有一个需要使用gpedit.msc,发现并不存在. 解决办法:升级到 Windows 10 专业版