第三部分 应用

在这一部分,我们会将前面两部分所了解到的内容和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. c# winforms TextBox的记忆功能

    c# winforms TextBox的记忆功能 1:在项目上点右键  sproperties-settings 添加项目 如 MyText  类型 String 2: 获取值:   string l ...

  2. java内存设置

    在上边红色框内加入java内存设置命令: -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m

  3. HTML 学习笔记 CSS3 (文本效果)

    text-shadow 语法 text-shadow : none | <length> none | [<shadow>, ] * <shadow> 或none ...

  4. O(1) 查询gcd

    我们来安利一个黑科技.(其实是Claris安利来的 比如我现在有一坨询问,每次询问两个不超过n的数的gcd. n大概1kw,询问大概300w(怎么输入就不是我的事了,大不了交互库 http://mim ...

  5. Visual Studio 2013编辑HTML文件无设计视图的解决方案

    在Visual Studio 2013中编辑HTML文件,会发现没有设计视图. 解决方法:点击Visual Studio 2013的”工具“菜单,再点击”选项“—>文本编辑器—>文件扩展名 ...

  6. BZOJ 1040 【ZJOI2008】 骑士

    Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...

  7. ORA-06519: active autonomous transaction detected and rolled back

    这个问题一般怎么解决 ?现在忙 待会贴详细代码  先给些路子..给位大大们 引用 楼主 green3365302 的回复: 这个问题一般怎么解决 ?现在忙 待会贴详细代码  先给些路子..给位大大们 ...

  8. Java多线程之Runable与Thread

    Java多线程是Java开发中的基础内容,但是涉及到高并发就有很深的研究可做了. 最近看了下<Java并发实战>,发先有些地方,虽然可以理解,但是自己在应用中很难下手. 所以还是先回顾一下 ...

  9. opencv6.1-imgproc图像处理模块之平滑与形态学操作

    这个部分是<opencv-tutorials.pdf>的部分,这部分也是几大部分中例子最多的,其实这个教程的例子都很不错,不过有些看得出来还是c接口的例子,说明例子有些年头了,其实在&qu ...

  10. 自己存档:ajax 动态提交form

    $.ajax({                    cache: true,                    type: "POST",                  ...