public class GestureTest extends Activity implements OnTouchListener{    @Overrideprotected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.main);    // init TextView          TextView tv = (TextView) findViewById(R.id.page);    // set OnTouchListener on TextView        tv.setOnTouchListener(this);    // show some text          tv.setText(R.string.text);         }    @Overridepublic boolean onTouch(View v, MotionEvent event) {             Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();                  return false;        }  我们给TextView的实例tv设定了一个onTouchListener,因为GestureTest类实现了OnTouchListener 接口,所以简单的给一个this作为参数即可。onTouch方法则是实现了OnTouchListener中的抽象方法,我们只要在这里添加逻辑代码即 可在用户触摸屏幕时做出响应,就像我们这里所做的——打出一个提示信息。 这里,我们可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN, ACTION_MOVE, ACTION_UP, 和ACTION_CANCEL。ACTION_DOWN是指按下触摸屏,ACTION_MOVE是指按下触摸屏后移动受力点,ACTION_UP则是指松 开触摸屏,ACTION_CANCEL不会由用户直接触发(所以不在今天的讨论范围,请参考ViewGroup.onInterceptTouchEvent(MotionEvent))。借助对于用户不同操作的判断,结合getRawX()、getRawY()、getX()和getY()等方法来获取坐标后,我们可以实现诸如拖动某一个按钮,拖动滚动条等功能。待机可以看看MotionEvent类的文档,另外也可以看考TouchPaint例子。 回到今天所要说的重点,当我们捕捉到Touch操作的时候,如何识别出用户的Gesture?这里我们需要GestureDetector.OnGestureListener接口的帮助,于是我们的GestureTest类就变成了这个样子。Java代码 public class GestureTest extends Activity implements OnTouchListener,             OnGestureListener {    ....    }  随后,在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给 GestureDetector 来分析是否有合适的callback函数来处理用户的手势。Java代码 @Overridepublicboolean onTouch(View v, MotionEvent event) {    // OnGestureListener will analyzes the given motion event return mGestureDetector.onTouchEvent(event);        }  接下来,我们实现了以下6个抽象方法,其中最有用的当然是onFling()、onScroll()和onLongPress()了。我已经把每一个方法代表的手势的意思写在了注释里,大家看一下就明白了。// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发Java代码 @Overridepublic boolean onDown(MotionEvent e) {    // TODO Auto-generated method stub      Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();         return false;    }    // 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发 // 注意和onDown()的区别,强调的是没有松开或者拖动的状态 @Overridepublic void onShowPress(MotionEvent e) {    // TODO Auto-generated method stub }       // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发Java代码 @Overridepublic boolean onSingleTapUp(MotionEvent e) {    // TODO Auto-generated method stub     return false;    }      // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发Java代码 @Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    float velocityY) {    // TODO Auto-generated method stub     return false;    }    // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发 @Overridepublicvoid onLongPress(MotionEvent e) {    // TODO Auto-generated method stub }    // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发 @Overridepublicboolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,    float distanceY) {    // TODO Auto-generated method stub      return  false;    }  我们来试着做一个onFling()事件的处理吧,onFling()方法中每一个参数的意义我写在注释中了,需要注意的是Fling事件的处理代 码中,除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,我们还可以根据用户在X轴或者Y轴上的 移动速度作为条件。比如下面的代码中我们就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。Java代码 @Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    float velocityY) {    // 参数解释: // e1:第1个ACTION_DOWN MotionEvent // e2:最后一个ACTION_MOVE MotionEvent // velocityX:X轴上的移动速度,像素/秒 // velocityY:Y轴上的移动速度,像素/秒 // 触发条件 : // X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    // Fling left Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();         } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    // Fling right       Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();         }         return  false;    }  问题是,这个时候如果我们尝试去运行程序,你会发现我们根本得不到想要的结果,跟踪代码的执行的会发现onFling()事件一直就没有被捕捉到。这正是一开始困扰我的问题,这到底是为什么呢? 我在讨论组的Gesture detection这个帖子里找到了答案,即我们需要在onCreate中tv.setOnTouchListener(this);之后添加如下一句代码。 tv.setLongClickable(true); 只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。 这次遇到的这个问题和上次MapView中setOnKeyListener遇到的问题挺类似,其实都是对SDK的了解不够全面,遇到了一次记住了就好。不过话说回来,Google在文档方面确实需要加强了,起码可以在OnGestureListener中说明需要满足那些条件才可以保证手势被正确识别。
Android里有两个类
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener

(另外android.widget.Gallery好像是更牛x的OnGestureListener )

1)
新建一个类继承SimpleOnGestureListener,HahaGestureDetectorListener
可以实现以下event事件。

boolean onDoubleTap(MotionEvent e)
解释:双击的第二下Touch down时触发

boolean onDoubleTapEvent(MotionEvent e)
解释:双击的第二下Touch down和up都会触发,可用e.getAction()区分。

boolean onDown(MotionEvent e)
解释:Touch down时触发

boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
解释:Touch了滑动一点距离后,up时触发。

void onLongPress(MotionEvent e)
解释:Touch了不移动一直Touch down时触发

boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
解释:Touch了滑动时触发。

void onShowPress(MotionEvent e)
解释:Touch了还没有滑动时触发
(与onDown,onLongPress比较
onDown只要Touch down一定立刻触发。

而Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。

所以Touchdown后一直不滑动,onDown->onShowPress->onLongPress这个顺序触发。


boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解释:上面这两个函数都是在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。

点击一下非常快的(不滑动)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed

点击一下稍微慢点的(不滑动)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed


2)在view的新建一个GestureDetector的对象。
构造函数里
gestureDetector = new GestureDetector(new HahaGestureDetectorListener());

然后在View的onTouchEvent里以下这样用,就可以在刚才1)弄的事件里写自己的代码了。
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
}

下面Android123一起用Android 2.0或以上SDK中的方法来实现如何通过应用层支持多点触控操作,对于常规的控件触控操作在内部为View的setOnTouchListener()接口实现的onTouchEvent()方法来处理。对于onTouchEvent方法的参数MotionEvent我们可以详细处理来实现对多点触控的了解,比如

  event.getAction() //获取触控动作比如ACTION_DOWN

  event.getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕

  event.getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引

  event.getX(nID); //获取第nID个触控点的x位置

  event.getY(nID); //获取第nID个点触控的y位置

  event.getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的

  event.getDownTime() //按下开始时间

  event.getEventTime() // 事件结束时间

  event.getEventTime()-event.getDownTime()); //总共按下时花费时间

更多相关文章

  1. Android打开WIFI或者移动网络的代码实现
  2. android webview显示HTML代码
  3. Android 获取电池基本信息代码
  4. android 打开新浪微博代码
  5. Android 中如何自己通过代码绘图
  6. Android 用户界面【level 1】
  7. android 使用代码实现 RelativeLayout布局
  8. android 亮屏及屏幕解锁代码
  9. Android屏蔽home键的代码,咋摁也不响应的方法

随机推荐

  1. Adding prebuilt shared library to Andr
  2. Android官方资料--Adoptable Storage
  3. Android(安卓)解析Html
  4. android dialog style属性设置
  5. Android(安卓)网络链接,不要忘记添加网络
  6. Android(安卓)Studio若干问题
  7. System Permissions—— android系统权限
  8. android stackView
  9. Android文件保存和读取
  10. 【Android(安卓)基础7.1 7.2】AsyncTask