现在的位置: 首页 > 综合 > 正文

android多点触控揭秘

2018年08月24日 ⁄ 综合 ⁄ 共 13115字 ⁄ 字号 评论关闭

转载:http://blog.csdn.net/cloudzfy1/article/details/6582707

最近需要做个Android的项目,需要使用多点触控的功能,上网找了很久,中文方面的资料相当少,英文方面也不多,经过自己的研究,加上对已知的一些资料的整理,下面为大家介绍一下Android多点触控程序的编写。

首先,我们准备好一张图片:

img.png

在Eclipse下新建一个Android工程(和一般Android工程一样),需要注意的是:Android的多点触控功能需要运行在Android 2.0版本以上。

工程

完成后,我们需要将原先准备好的图片放进res/drawable文件夹下(注意,如果是Android2.2,请放在三个drawable文件夹下),如图所示:

该图片是为了给该多点触控的实例提供运行环境,实现图片的放大和缩小。

下面,我们来修改一下main.xml文件,如下所示:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ImageView android:id="@+id/imageView"  
  8.             android:layout_width="fill_parent"  
  9.             android:layout_height="fill_parent"  
  10.             android:src="@drawable/img"  
  11.             android:scaleType="matrix" >  
  12. </ImageView>  
  13. </LinearLayout>  

对于让一张静态图片在Android面板上显示,我们可以采用下面的一句话:

  1. ImageView imageView = (ImageView)findViewById(R.id.imageView);  

 

通过设置Matrix,我们可以获得对ImageView的一些基本操作。

OK,啰嗦这么多,下面进入主题:

我们需要实现一个OnTouchListener的方法,来设置ImageView的侦听属性,该接口位于android.view.View.OnTouchListener。

实现onTouch(View view, MotionEvent event)的方法,就可以获取触屏的感应事件了。

在该事件中,有两个参数可以用来获取对触摸的控制,这两个参数分别为:MotionEvent.getAction()和MotionEvent.ACTION_MASK,前者用于对单点触控进行操作,后者用于对多点触控进行操作,相应地,我们可以通过Android Developers’ Reference看到,对于单点触控,我们由MotionEvent.getAction()可以得到以下几种事件:ACTION_DOWN、ACTION_UP,而对于多点触控,由MotionEvent.ACTION_MASK,我们可以得到:ACTION_POINTER_DOWN、ACTION_POINTER_UP,都是MotionEvent中的常量,可以直接调用。而有些常量则是单点和多点共用的,如:ACTION_MOVE,因此在按下时,我们必须标记单点与多点触控的区别。

下面我们来介绍一下缩放功能的实现,对于缩放,我们定义有两种手势,一种是双指拉伸式,一种是单指旋转式。

首先,双指拉伸式。

这是一种比较常规的图片缩放方式,实现起来也比较方便,我们可以很容易想到,在处理多点触控事件时,如果没有别的手势干扰,我们只需检测两指按下时和移动之后的位置关系即可,如果距离变大,则是放大图片;反之则是缩小图片。

主要代码如下:

 

  1. if(mode == ZOOM)  
  2. {  
  3.     float newDistance;  
  4.     newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));  
  5.     if(newDistance > 10f) {  
  6.         matrix.set(savedMatrix);  
  7.         matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);  
  8.         oldDistance = newDistance;  
  9.         savedMatrix.set(matrix);  
  10.     }  
  11. }  

然后,单指旋转式。

这是一种单指操作中比较流行的方式,然而实现起来并非特别方便。具体说来,我们可以定义顺时针转动为图片放大,逆时针转动为图片缩小。在没有其他干扰项的时候,我们可以通过捕获三次连续移动来得知手势顺时针还是逆时针。如下图所示,我们把前两次的位置作一个向量A,后两次位置作一个向量B,如果向量B比向量A大,则是逆时针;向量B比向量A小则是顺时针。当然,我们这里就要用到反三角函数,同时要注意2pi的角度问题哦~

注意:在处理同为单指操作或者同为多指操作的时候,要考虑不同行为之间的区别。

主要代码如下:

  1. if (mode == MOVE)  
  2. {  
  3.     if(rotate == NONE) {  
  4.         savedMatrix.set(matrix);  
  5.         mid.set(event.getX(), event.getY());  
  6.         rotate = ROTATION;  
  7.     }  
  8.     else {  
  9.         matrix.set(savedMatrix);  
  10.         double a = Math.atan((mid.y-start.y)/(mid.x-start.x));  
  11.         double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));  
  12.         if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {  
  13.             matrix.postScale((float)0.9, (float)0.9);  
  14.         }  
  15.         else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {  
  16.         matrix.postScale((float)1.1, (float)1.1);  
  17.         }  
  18.         start.set(event.getX(), event.getY());  
  19.         rotate = NONE;  
  20.     }  
  21. }  

下面是实现的结果截图:

 初始画面:

通过鼠标顺时针转动后的效果图:

通过鼠标逆时针转动后的效果图:

下面是代码的具体解析:

TouchActivity.java

 

  1. package example.MultiTouch;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Matrix;  
  5. import android.graphics.PointF;  
  6. import android.os.Bundle;  
  7. import android.view.MotionEvent;  
  8. import android.view.View;  
  9. import android.view.View.OnTouchListener;  
  10. import android.widget.ImageView;  
  11.   
  12. public class TouchActivity extends Activity {  
  13.       
  14.     private static final int NONE = 0;  
  15.     private static final int MOVE = 1;  
  16.     private static final int ZOOM = 2;  
  17.       
  18.     private static final int ROTATION = 1;  
  19.       
  20.     private int mode = NONE;  
  21.     private Matrix matrix = new Matrix();  
  22.     private Matrix savedMatrix = new Matrix();  
  23.     private PointF start = new PointF();  
  24.     private PointF mid = new PointF();  
  25.     private float s = 0;  
  26.     private float oldDistance;  
  27.     private int rotate = NONE;  
  28.     @Override  
  29.     public void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.main);  
  32.           
  33.         ImageView imageView = (ImageView)findViewById(R.id.imageView);  
  34.         imageView.setOnTouchListener(new OnTouchListener()  
  35.         {  
  36.   
  37.             @Override  
  38.             public boolean onTouch(View view, MotionEvent event) {  
  39.                 ImageView imageView = (ImageView)view;  
  40.                 switch (event.getAction()&MotionEvent.ACTION_MASK) {  
  41.                 case MotionEvent.ACTION_DOWN:  
  42.                     savedMatrix.set(matrix);  
  43.                     start.set(event.getX(), event.getY());  
  44.                     mode = MOVE;  
  45.                     rotate = NONE;  
  46.                     break;  
  47.                 case MotionEvent.ACTION_UP:  
  48.                 case MotionEvent.ACTION_POINTER_UP:  
  49.                     mode = NONE;  
  50.                     break;  
  51.                 case MotionEvent.ACTION_POINTER_DOWN:  
  52.                     oldDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));  
  53.                     if (oldDistance > 10f) {  
  54.                         savedMatrix.set(matrix);  
  55.                         mid.set((event.getX(0)+event.getX(1))/2, (event.getY(0)+event.getY(1))/2);  
  56.                         mode = ZOOM;  
  57.                     }  
  58.                 case MotionEvent.ACTION_MOVE:  
  59.                     if (mode == MOVE)  
  60.                     {  
  61.                         if(rotate == NONE) {  
  62.                             savedMatrix.set(matrix);  
  63.                             mid.set(event.getX(), event.getY());  
  64.                             rotate = ROTATION;  
  65.                         }  
  66.                         else {  
  67.                             matrix.set(savedMatrix);  
  68.                             double a = Math.atan((mid.y-start.y)/(mid.x-start.x));  
  69.                             double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));  
  70.                             if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {  
  71.                                 matrix.postScale((float)0.9, (float)0.9);  
  72.                             }  
  73.                             else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {  
  74.                                 matrix.postScale((float)1.1, (float)1.1);  
  75.                             }  
  76.                             start.set(event.getX(), event.getY());  
  77.                             rotate = NONE;  
  78.                         }  
  79.                     }  
  80.                     else if(mode == ZOOM)  
  81.                     {  
  82.                         float newDistance;  
  83.                         newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));  
  84.                         if(newDistance > 10f) {  
  85.                             matrix.set(savedMatrix);  
  86.                             matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);  
  87.                             oldDistance = newDistance;  
  88.                             savedMatrix.set(matrix);  
  89.                         }  
  90.                     }  
  91.                     break;  
  92.                 }  
  93.                 imageView.setImageMatrix(matrix);  
  94.                 return true;  
  95.             }  
  96.               
  97.         });  
  98.     }  
  99. }  

AndroidManifest.xml

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="example.MultiTouch"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="8" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".TouchActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>  

抱歉!评论已关闭.