以前做项目只是简单应用一些点击事件以及滑动事件,有些细节方便不是很清楚,今天特意学习了一下,顺便分享,以便于以后的记忆
一、先说点击事件:
点击事件很简单,我们只要绑定点击事件的监听接口并实现点击事件的监听方法,在onClik方法中进行点击事件的处理即可。如点击事件监听接口OnClickListener、长按事件的监听接口OnLongClickListener等。下面是一个点击事件的简单实现过程:
class CliclLister implements OnClickListener{
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.but:
if(v.isPressed()){
btn.setText("单击成功");
}else{
btn.setText("单击");
}
break;
}
}
}
Button绑定监听事件后,点击Button可以出发该事件,if(v.idPressed)内部的代码可以执行,但else后面的代码是不会执行的,如果我们想捕获点击事件时按下与弹起的这些动作,在该方法内是无法完成的。那如果我们详见听点击事件的按下与弹起怎么做呢?其实很简单,一种方法是我们自定义View,在自定义的View里面重写onTouchEvent方法实现这些手势的监听,不过这种方法是很愚蠢的,我们就只是想监听一下用户的简单手势还需要重写View的方法。其实还有更加简单的方法了,呵呵。。
二、再说OnTouchListener
最简单的方法就是实现OnTouchListener接口,在该接口中实现OnTouch方法來监听用户的手势操作。这里注意一下,如果我们为某一控件设置了OnTouchListener监听,那么该View本身内部的onTouchEvent方法是否会执行就要看OnTouchListener接口中onTouch方法的返回值了,如果返回值是true,那么View本身内部的onTouchEvent方法不会被调用,如果返回的是false,那么onTouchEvent也会被正常调用。由此可见OnTouchListener监听事件的优先级要比onTouchEvent高。
下面简单看一下OnTouchListener的简单实现:
public class MainActivity extends Activity {
private Button but;
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but = (Button) findViewById(R.id.but);
text = (TextView) findViewById(R.id.text);
but.setOnTouchListener(new MyTouchListener());
but.setOnClickListener(new MyClickListener());
}
class MyTouchListener implements OnTouchListener{
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
but.setText("已经按下按钮");
break;
case KeyEvent.ACTION_UP:
but.setText("按钮以弹起");
break;
default:
break;
}
return true;
}
}
class MyClickListener implements OnClickListener{
@Override
public void onClick(View v) {
if(v.getId() == R.id.but){
text.setText("您点击成功这个按钮了!!");
text.setTextColor(Color.RED);
}
}
}
}
代码很简单,Button绑定了两个监听,一个是OnTouchListener,一个是OnClickListener,我们点击这个按钮后发现,OnTouchListener的监听方法执行了,而OnClickListener得监听方法没有执行。
其实上面已经介绍过,我们OnTouchListener的onTouch方法返回值为true,这表示事件只由它内部处理,不会传递给View的onTouchEvent,而OnClickListener得执行过程是在onTouchEvent之后,如果在onTouchEvent方法中,发现当前View设置了OnClickListener,就去处理它的onClick事件,由此可得出事件处理的一个优先级:
OnTouchListener -> onTouchEvent -> OnClickListener
三、GestureDetector强势来袭
当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等。通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)。Android sdk给我们提供了GestureDetector(Gesture:手势Detector:识别)类,通过这个类我们可以识别很多的手势。GestureDetector虽然能够处理手势,但不同手势的处理是留给程序员自己处理。
GestureDetector类对外提供两个接口和一个内部类:
接口:OnGestureListener,OnDoubleTapListener
内部类:SimpleOnGestureListener
下面我们先看OnGestureListener接口:
(1)GestureDetector.OnGestureListener---接口
class MyGestureDetector implements OnGestureListener{
@Override
public boolean onDown(MotionEvent e) {
// 用户按下屏幕就会触发;
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// 如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行,具体这个瞬间是多久
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// 一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以也就不会触发这个事件
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// 在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// 长时间点击事件
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// 滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
return false;
}
}
我们在创建一个GestureDetector需要三部:
1.创建OnGestureListener监听函数,可以使用构造实例,也可以使用构造类。
OnGestureListener listener = newOnGestureListener(){
}或
class MyGestureListener implements OnGestureListener{
}
2.创建GestureDetector 实例gestureDetector,构造函数有三个,我们可以根据需要选择
GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
3.在OnTouchListener的onTouch方法中拦截事件
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
4.控件绑定监听
TextView tv = (TextView)findViewById(R.id.tv);
tv.setOnTouchListener(this);
下面看一个简单的实现
首先,在主布局页面添加一个textView,方便在其上的手势识别,将textView放的比较大,并且用户的手势监听会以textview显示出来,方便查看手势监听的过程,布局文件代码为:
下面是Java代码,代码中监听在TextView上的手势,并且将手势的监听过程打印在TextView上,具体代码如下:
public class ActivityOnGestureOne extends Activity implements OnTouchListener{
private TextView text;
private Button but;
GestureDetector myGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ongesture_listener);
init();
}
private void init() {
text = (TextView) findViewById(R.id.text);
but = (Button) findViewById(R.id.but);
myGestureDetector = new GestureDetector(new MyGestureListener()); //使用派生自OnGestureListener
text.setOnTouchListener(this);
text.setFocusable(true);
text.setClickable(true);
text.setLongClickable(true);
but.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
text.setText("");
}
});
}
//将捕捉到的MotionEvent交给GestureDetector
@Override
public boolean onTouch(View v, MotionEvent event) {
return myGestureDetector.onTouchEvent(event);
}
class MyGestureListener implements OnGestureListener{
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
@Override
public boolean onDown(MotionEvent e) {
text.append(" onDown ");
Log.i("MyGesture", "onDown");
return false;
}
/*
* 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
* 注意和onDown()的区别,强调的是没有松开或者拖动的状态
*
* 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,
* 也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,
* 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间
* (这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress)拖动了,就不执行onShowPress。
*/
@Override
public void onShowPress(MotionEvent e) {
text.append(" onShowPress ");
Log.i("MyGesture", "onShowPress");
}
/*用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
轻击一下屏幕,立刻抬起来,才会有这个触发
从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应 */
@Override
public boolean onSingleTapUp(MotionEvent e) {
text.append(" onSingleTapUp ");
Log.i("MyGesture", "onSingleTapUp");
return true;
}
// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
text.append(" onScroll ");
Log.i("MyGesture", "onScroll");
return true;
}
// 用户长按触摸屏后会触发
@Override
public void onLongPress(MotionEvent e) {
text.append(" onLongPress ");
Log.i("MyGesture", "onLongPress");
}
// 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
text.append(" onFling ");
Log.i("MyGesture", "onFling");
return true;
}
}
}
读者可以自己通过手势监听的打印自己分析一下监听过程,下面是我截取的一张点击TextView并且滑动的截图:
(2)GestureDetector.OnDoubleTapListener---接口