在使用自定义视图的时候,对触屏事件的处理是比不可少的,有能力的能够本身写代码处理,这样更加的灵活。若是不想这么麻烦,Android提供了一个手势监听类GestureDetector,能够供咱们使用。GestureDetector使用很方便,提供了单击,双击,长按等操做的处理,可是通常的定义界面都比较复杂,还用不少须要注意的地方,在这儿总结一下GestureDetector的使用。android
首先新建一个空白的工程,主界面的layout中只须要添加一个按钮就行web
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
缓存
xmlns:tools="http://schemas.android.com/tools"
app
android:layout_width="match_parent"
框架
android:layout_height="match_parent"
ide
android:paddingBottom="@dimen/activity_vertical_margin"
函数
android:paddingLeft="@dimen/activity_horizontal_margin"
测试
android:paddingRight="@dimen/activity_horizontal_margin"
this
android:paddingTop="@dimen/activity_vertical_margin"
spa
tools:context=".MainActivity" >
<Button
android:id="@+id/btn_textgesture"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/app_name" />
</RelativeLayout>
复制代码
因为要测试的触屏事件,全部这个按钮比较大,主界面为以下效果: 首先介绍一下触屏事件处理的基本思路。触屏通常有三个基本事件,down按下,move移动,up离开,经过对这三个基本事件的监听,判断用户执行了何种操做。一个标准的触屏操做通常都是一系列基本事件的组合,在Android的框架中,经过onTouch()函数能够获取基本的触屏事件,而像onClick这样的函数,已是一系列基本事件的组合。好比,发生了Down事件,在up事件以前没有发生move事件,或者move的范围很小,而且down事件和up事件的间隔很短,这就是一个click或者singelTap事件,对比实体键盘按键的事件,实体键盘是在down事件发生后进行操做,而触屏事件通常是up事件发生后进行操做。下面是activity的代码
package com.example.testgesture;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button mButton;
private GestureDetector mGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGestureDetector = new GestureDetector(this, new MyOnGestureListener());
mButton = (Button) findViewById(R.id.btn_textgesture);
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));
mGestureDetector.onTouchEvent(event);
// 必定要返回true,否则获取不到完整的事件
return true;
}
});
}
private String getActionName(int action) {
String name = "";
switch (action) {
case MotionEvent.ACTION_DOWN: {
name = "ACTION_DOWN";
break;
}
case MotionEvent.ACTION_MOVE: {
name = "ACTION_MOVE";
break;
}
case MotionEvent.ACTION_UP: {
name = "ACTION_UP";
break;
}
default:
break;
}
return name;
}
class MyOnGestureListener extends SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.i(getClass().getName(), "onSingleTapUp-----" + getActionName(e.getAction()));
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.i(getClass().getName(), "onLongPress-----" + getActionName(e.getAction()));
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.i(getClass().getName(),
"onScroll-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("
+ e2.getX() + "," + e2.getY() + ")");
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i(getClass().getName(),
"onFling-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("
+ e2.getX() + "," + e2.getY() + ")");
return false;
}
@Override
public void onShowPress(MotionEvent e) {
Log.i(getClass().getName(), "onShowPress-----" + getActionName(e.getAction()));
}
@Override
public boolean onDown(MotionEvent e) {
Log.i(getClass().getName(), "onDown-----" + getActionName(e.getAction()));
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.i(getClass().getName(), "onDoubleTap-----" + getActionName(e.getAction()));
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.i(getClass().getName(), "onDoubleTapEvent-----" + getActionName(e.getAction()));
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.i(getClass().getName(), "onSingleTapConfirmed-----" + getActionName(e.getAction()));
return false;
}
}
}
复制代码
首先是声明一个GestureDetector,而后重写Button的onTouch函数,将触屏事件交给GestureDetector处理。 首先作一个对按钮作一个单击public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
复制代码
e1为第一次按下的事件,和onDown事件里面的同样,e2为当前的事件,distanceX为本次onScroll移动的X轴距离,distanceY为移动的Y轴距离,移动的距离是相对于上一次onScroll事件的移动距离,而不是当前点和按下点的距离。此次滑动最后触发了onFling事件,可是onFling事件的触发不是必定的,onFling是在ACTION_UP触发,平时列表在离开屏幕是继续滚动,就是经过这种方式触发。public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
复制代码
onFling的前两个参数和onScroll相同,e2为用户拖动完离开屏幕时的点。veloctiyX,velocitY为离开屏幕时的初始速度,以这两个速度为初始速度作匀减速运动,就是如今拖动列表和拖动图片的各类缓存滚动的效果。 函数的返回值除了onLongPress,这些函数都是有返回值的,mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));
mGestureDetector.onTouchEvent(event);
// 必定要返回true,否则获取不到完整的事件
return true;
}
});
复制代码
这些返回值会经过 mGestureDetector.onTouchEvent(event); 传递给onTouch。