Android中用户手势检测详述(OnCliskListener、OnTouchListener和GestureDetecter)

以前做项目只是简单应用一些点击事件以及滑动事件,有些细节方便不是很清楚,今天特意学习了一下,顺便分享,以便于以后的记忆

一、先说点击事件:

点击事件很简单,我们只要绑定点击事件的监听接口并实现点击事件的监听方法,在onClik方法中进行点击事件的处理即可。如点击事件监听接口OnClickListener、长按事件的监听接口OnLongClickListener等。下面是一个点击事件的简单实现过程:

<span style="font-size:14px;"><span style="font-family:SimSun;font-size:14px;">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;
		}
	}
}
</span></span>
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的简单实现:

<span style="font-size:14px;"><span style="font-family:SimSun;font-size:14px;">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);
			}
		}
    	
    }
}</span></span>
代码很简单,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---接口

<span style="font-size:14px;">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;
		}
    	
    }</span>
我们在创建一个GestureDetector需要三部:

1.创建OnGestureListener监听函数,可以使用构造实例,也可以使用构造类。
OnGestureListener listener = newOnGestureListener(){
    }或
class MyGestureListener implements OnGestureListener{

}

2.创建GestureDetector 实例gestureDetector,构造函数有三个,我们可以根据需要选择

<span style="font-size:14px;">    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);</span>
3.在OnTouchListener的onTouch方法中拦截事件

<span style="font-size:14px;">public boolean onTouch(View v, MotionEvent event) {  
        return gestureDetector.onTouchEvent(event);     
    }</span>

4.控件绑定监听

<span style="font-size:14px;">TextView tv = (TextView)findViewById(R.id.tv);  
tv.setOnTouchListener(this); </span>

下面看一个简单的实现

首先,在主布局页面添加一个textView,方便在其上的手势识别,将textView放的比较大,并且用户的手势监听会以textview显示出来,方便查看手势监听的过程,布局文件代码为:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView 
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/green"
        android:gravity="center"
        android:textSize="16dp"/>
    
    <Button 
        android:id="@+id/but"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="清除"/>
</LinearLayout>
下面是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---接口


  



你可能感兴趣的:(Android学习,手势监听)