Android单点触摸与多点触摸

测试单点触摸事件,它适用于所有android版本。我们在视图中注册一个OnTouchListener接口,并把触摸时间传递给这个接口实现。OnTouchListener接口只有一个方法:public abstract boolean onTouch(View  v, MotionEvent event)

第一个参数是分派该触摸事件的View,第二个参数是获得触摸事件的参数。

OnTouchListener可在任何View中实现中通过View.setOnTouchListener方法进行注册。在MotionEvent被分派给View本身之前会先调用OnTouchListener方法。我们可在onTouch()方法的实现中返回true通知该View,我们已经处理事件。如果返回为false,那么View将自己处理该事件。

MotionEvent实例包含如下3个我们关心的方法:

MotionEvent.getX()和MotionEvent.getY();这两个方法报告触摸事件相对于View的X和Y坐标。坐标原点位于该视图左上角,X轴指向右边,Y轴指向下。坐标是以像素为单位。该方法返回浮点型数据,因此该坐标具有亚像素精度。

MotionEvent.getAction():返回触摸事件的类型。它是一个整型数,具有如下值之一:MotionEvent.ACTION_DOWN、

MotionEvent.ACTION_MOVE、MotionEvent.ACTION_CANCEL和MotionEvent.ACTION_UP。

顾名思义,当手指触摸屏幕时,将触发MotionEvent.ACTION_DOWN事件。

当手指移动时,则触发MotionEvent.ACTION_MOVE事件。只要手指没有完全脱离屏幕,总可以获得MotionEvent.ACTION_MOVE事件

当手指再次离开屏幕时,MotionEvent.ACTION_UP事件就会触发。

MotionEvent.ACTION_CANCEL事件则稍微神秘。文档说明当前手势取消时会触发该事件,我们还是把它假设为MotionEvent.ACTION_UP事件。

下面是测试代码:

[java]  view plain  copy
  1. package org.example.ch04_android_basics;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.MotionEvent;  
  7. import android.view.View;  
  8. import android.view.View.OnTouchListener;  
  9. import android.widget.TextView;  
  10.   
  11. public class SingleTouchTest extends Activity implements OnTouchListener{  
  12.     StringBuilder builder = new StringBuilder();  
  13.     TextView textView;  
  14.   
  15.     @Override  
  16.     public boolean onTouch(View v, MotionEvent event) {  
  17.         // TODO Auto-generated method stub  
  18.         builder.setLength(0);  
  19.         switch(event.getAction()){  
  20.         case MotionEvent.ACTION_DOWN:  
  21.             builder.append("down, ");  
  22.             break;  
  23.         case MotionEvent.ACTION_MOVE:  
  24.             builder.append("move, ");  
  25.             break;  
  26.         case MotionEvent.ACTION_CANCEL:  
  27.             builder.append("cancle, ");  
  28.             break;  
  29.         case MotionEvent.ACTION_UP:  
  30.             builder.append("up, ");  
  31.             break;  
  32.         }  
  33.         builder.append(event.getX());  
  34.         builder.append(", ");  
  35.         builder.append(event.getY());  
  36.         String text = builder.toString();  
  37.         Log.d("TouchTest", text);  
  38.         textView.setText(text);  
  39.         return true;  
  40.     }  
  41.   
  42.     @Override  
  43.     protected void onCreate(Bundle savedInstanceState) {  
  44.         // TODO Auto-generated method stub  
  45.         super.onCreate(savedInstanceState);  
  46.         textView = new TextView(this);  
  47.         textView.setText("Touch and drag (one finger only)!");  
  48.         textView.setOnTouchListener(this);  
  49.         setContentView(textView);  
  50.     }  
  51.       
  52. }  

    对于处理多点触摸事件就复杂的多,Android2.2版本后对多点触摸做了修改,添加了新的方法和常量,甚至重命名了常量。这些改变可能会让处理多点触摸容易些。不过只支持Android2.2以后的版本,为了支持Android2.0--Android2.21版本,我们使用Android2.0的API。

    当处理多点触摸事件时,我们使用重载的方法,它们带有一个所谓的指针索引,如event.getX(pointerIndex);

    pointIndex是MotionEvent的内部数组中的一个索引,它包含特定手指触摸屏幕事件的坐标值。而真正识别屏幕上的一根手指是指针ID。指针ID是一个任意数字,可以唯一标识触摸屏幕的一个指针的实例。有一个方法MotionEvent.getPointerIdentifier(int pointerIndex),它返回一个基于指针索引的指针ID。只要手指还触摸在屏幕上,一个指针ID就与一根手指保持相同,而指针索引就不一定这样了。先来看看是如何获取指针索引:

    int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;

    ACTION_POINTER_ID_MASK的常量的值是0xff00,因此低8位为0,高8位为15,用于保存事件的指针索引。

    整数的低8位可从event.getAction()方法返回得到,用于保存事件类型的值。我们通过MotionEvent.ACTION_POINTER_ID_SHIFT来移位,该值为8,因此实际上是将第15位移到第8位,第7位移到第0位。注意我们是获取pointerIndex而常量却是XXX_POINTER_ID_XXX而不是XXX_POINTER_INDEX_XXX

    获取事件类型,我们只需屏蔽指针索引:

    int action = event.getAction() & MotionEvent.ACTION_MASK;

    这里我们会遇到新的事件类型,

    MotionEvent.ACTION_POINTER_DOWN:除了第一根手指外的任何手指触摸屏幕,都将发生该事件,而第一根手指仍然产生MotionEvent.ACTION_DOWN事件。

    MotionEvent.ACTION_POINTER_UP:多根手指触摸屏幕而一根手指离开屏幕时,将发生该事件。最后一根手指离开屏幕将产生MotionEvent.ACTION_UP事件,而该手指不一定是第一个触摸屏幕的手指。为了检查单个MotionEvent中包含几个事件,可使用MotionEvent.getPointerCount()方法,它会告诉我们MotionEvent中包含多少根手指的坐标。然后我们可通过MotionEvent.getX()、

    MotionEvent.getY()和MotionEvent.getPointerId()方法来得到指针ID和从指针索引0到MotionEvent.getPointerCount() - 1的坐标值。

    测试代码如下:

    [java]  view plain  copy
    1. package org.example.ch04_android_basics;  
    2.   
    3. import android.app.Activity;  
    4. import android.os.Bundle;  
    5. import android.view.MotionEvent;  
    6. import android.view.View;  
    7. import android.view.View.OnTouchListener;  
    8. import android.widget.TextView;  
    9.   
    10. public class MultiTouchTest extends Activity implements OnTouchListener {  
    11.     StringBuilder builder = new StringBuilder();  
    12.     TextView textView;  
    13.     float[] x = new float[10];  
    14.     float[] y = new float[10];  
    15.     boolean[] touched = new boolean[10];  
    16.     int[] id = new int[10];  
    17.       
    18.     private void updateTextView(){  
    19.         builder.setLength(0);  
    20.         for(int i = 0; i < 10; i++){  
    21.             builder.append(touched[i]);  
    22.             builder.append(", ");  
    23.             builder.append(id[i]);  
    24.             builder.append(", ");  
    25.             builder.append(x[i]);  
    26.             builder.append(", ");  
    27.             builder.append(y[i]);  
    28.             builder.append("\n");  
    29.         }  
    30.         textView.setText(builder);  
    31.     }  
    32.   
    33.     @Override  
    34.     protected void onCreate(Bundle savedInstanceState) {  
    35.         // TODO Auto-generated method stub  
    36.         super.onCreate(savedInstanceState);  
    37.         textView = new TextView(this);  
    38.         textView.setText("Touch and drag (multiple fingers supported)!");  
    39.         textView.setOnTouchListener(this);  
    40.         setContentView(textView);  
    41.         for(int i = 0; i < 10; i++){  
    42.             id[i] = -1;  
    43.         }  
    44.         updateTextView();  
    45.     }  
    46.   
    47.     @Override  
    48.     public boolean onTouch(View v, MotionEvent event) {  
    49.         // TODO Auto-generated method stub  
    50.         int action = event.getAction() & MotionEvent.ACTION_MASK;  
    51.         int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >>  
    52.             MotionEvent.ACTION_POINTER_ID_SHIFT;  
    53.         int pointerCount = event.getPointerCount();  
    54.         for(int i = 0; i < 10; i++){  
    55.             if(i >= pointerCount){  
    56.                 touched[i] = false;  
    57.                 id[i] = -1;  
    58.                 continue;  
    59.             }  
    60.             if(event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex){  
    61.                 /* If it's an up/down/cancel/out event, mask the id to see if  
    62.                 we should process it for this touch point */  
    63.                 continue;  
    64.             }  
    65.             int pointerId = event.getPointerId(i);  
    66.             switch(action){  
    67.             case MotionEvent.ACTION_DOWN:  
    68.             case MotionEvent.ACTION_POINTER_DOWN:  
    69.                 touched[i] = true;  
    70.                 id[i] = pointerId;  
    71.                 x[i] = (int)event.getX(i);  
    72.                 y[i] = (int)event.getY(i);  
    73.                 break;  
    74.             case MotionEvent.ACTION_UP:  
    75.             case MotionEvent.ACTION_POINTER_UP:  
    76.             case MotionEvent.ACTION_OUTSIDE:  
    77.             case MotionEvent.ACTION_CANCEL:  
    78.                 touched[i] = false;  
    79.                 id[i] = -1;  
    80.                 x[i] = (int)event.getX(i);  
    81.                 y[i] = (int)event.getY(i);  
    82.                 break;  
    83.             case MotionEvent.ACTION_MOVE:  
    84.                 touched[i] = true;  
    85.                 id[i] = pointerId;  
    86.                 x[i] = (int)event.getX(i);  
    87.                 y[i] = (int)event.getY(i);  
    88.                 break;  
    89.             }  
    90.         }  
    91.         updateTextView();  
    92.         return true;  
    93.     }  
    94.   
    95. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值