码迷,mamicode.com
首页 > 移动开发 > 详细

Android 手势监听学习总结

时间:2015-08-29 21:42:16      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:手势

android的简单手势监听一般用onTouchListner接口,复杂手势监听一般用Detector来接替onTouch的处理。

手势监听后的处理涉及android坐标系统的问题。

多点触点则一般用event.getPointerCount()获取目前的触摸点的个数,用event.getX(index)、event.getY(index)获得第index个触摸点的坐标。


一. 用View.OnTouchListener接口监听简单手势

在Android中,简单的手势监听用实现View类的View.OnTouchListener接口的方法即可


如,对某个view进行手势监听

RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rlayout);

		relativeLayout.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					// 按下屏幕的操作
					break;
				case MotionEvent.ACTION_MOVE:
					// 在屏幕上移动的操作
					break;
				case MotionEvent.ACTION_UP:
					// 离开屏幕的操作
					break;
				case (MotionEvent.ACTION_CANCEL):
					// 手势撤消的操作
					// 一般认为不能由用户主动触发。
					// 系统在运行到一定程度下无法继续响应你的后续动作时会产生此事件
					break;
				default:
					break;
				}
				// 这个返回值如果是false的话,那么它只会接受到第一个ACTION_DOWN的效果,
				// 后面的它认为没有触发,所以要想继续监听后续事件,需要返回值为true
				return true;
			}
		});

需要注意的是,onTouch()方法要返回true,否则只会监听ACTION_DOWN


也可以对整个Activity进行监听,如:

public class MyActivity extends Activity {

	private static final String DEBUG_TAG = "MyActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = MotionEventCompat.getActionMasked(event);

		switch (action) {
		case (MotionEvent.ACTION_DOWN):
			Log.d(DEBUG_TAG, "Action was DOWN");
			break;
		case (MotionEvent.ACTION_MOVE):
			Log.d(DEBUG_TAG, "Action was MOVE");
			break;
		case (MotionEvent.ACTION_UP):
			Log.d(DEBUG_TAG, "Action was UP");
			break;
		case (MotionEvent.ACTION_CANCEL):
			Log.d(DEBUG_TAG, "Action was CANCEL");
			break;
		default:
			break;
		}
		return true;
	}

}

二. 用GestureDetector监听复杂手势

对于复杂手势的监听,一般用GestureDetector,而且为了提高版本的兼容,一般用support.v4中的GestureDetectorCompat

如:对某个view进行手势监听

package com.example.touch;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;

public class MyActivity2 extends Activity {

	private static final String TAG = "MyActivity2";

	// 用GestureDetectorCompat替换GestureDetector,GestureDetectorCompat兼容的版本较广
	private GestureDetectorCompat mDetector;

	private LinearLayout linearLayout;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initView();

		initDetector();

		setTouchListener();
	}

	// 对linearLayout设置手势监听
	private void setTouchListener() {
		linearLayout.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				mDetector.onTouchEvent(event);
				return true;
			}
		});
	}

	// // 让GestureDetectorCompat来接替处理
	// @Override
	// public boolean onTouchEvent(MotionEvent event){
	// this.mDetector.onTouchEvent(event);
	// // Be sure to call the superclass implementation
	// return super.onTouchEvent(event);
	// }

	private void initView() {
		linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
	}

	// 初始化手势监听器Detector
	private void initDetector() {
		mDetector = new GestureDetectorCompat(MyActivity2.this,
				new MytGestureListener());
	}

	/**
	 * 手势监听器
	 */
	private class MytGestureListener extends SimpleOnGestureListener {

		// Touch down时触发
		@Override
		public boolean onDown(MotionEvent e) {
			Log.d(TAG, "onDown");
			return super.onDown(e);
		}

		// 在Touch down之后一定时间(115ms)触发
		@Override
		public void onShowPress(MotionEvent e) {
			Log.d(TAG, "onShowPress");
		}

		// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			Log.d(TAG, "onSingleTapUp");
			return super.onSingleTapUp(e);
		}

		// 滑动时触发
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			Log.d(TAG, "onScroll");
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		// 抛掷
		// 滑动一段距离,up时触发
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			Log.d(TAG, "onFling");
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		// 长按后触发(Touch down之后一定时间(500ms))
		@Override
		public void onLongPress(MotionEvent e) {
			Log.d(TAG, "onLongPress");
		}
	}

}


对整个Activity进行监听

package com.example.touch;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class MyActivity2 extends Activity {

	private static final String TAG = "MyActivity2";

	// 用GestureDetectorCompat替换GestureDetector,GestureDetectorCompat兼容的版本较广
	private GestureDetectorCompat mDetector;

	private LinearLayout linearLayout;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initView();

		initDetector();

		// setTouchListener();
	}

	// // 对linearLayout设置手势监听
	// private void setTouchListener() {
	// linearLayout.setOnTouchListener(new OnTouchListener() {
	// @Override
	// public boolean onTouch(View v, MotionEvent event) {
	// mDetector.onTouchEvent(event);
	// return true;
	// }
	// });
	// }

	// 让GestureDetectorCompat来接替处理
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		this.mDetector.onTouchEvent(event);
		// Be sure to call the superclass implementation
		return super.onTouchEvent(event);
	}

	private void initView() {
		linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
	}

	// 初始化手势监听器Detector
	private void initDetector() {
		mDetector = new GestureDetectorCompat(MyActivity2.this,
				new MytGestureListener());
	}

	/**
	 * 手势监听器
	 */
	private class MytGestureListener extends SimpleOnGestureListener {

		// Touch down时触发
		@Override
		public boolean onDown(MotionEvent e) {
			Log.d(TAG, "onDown");
			return super.onDown(e);
		}

		// 在Touch down之后一定时间(115ms)触发
		@Override
		public void onShowPress(MotionEvent e) {
			Log.d(TAG, "onShowPress");
		}

		// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			Log.d(TAG, "onSingleTapUp");
			return super.onSingleTapUp(e);
		}

		// 滑动时触发
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			Log.d(TAG, "onScroll");
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		// 抛掷
		// 滑动一段距离,up时触发
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			Log.d(TAG, "onFling");
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		// 长按后触发(Touch down之后一定时间(500ms))
		@Override
		public void onLongPress(MotionEvent e) {
			Log.d(TAG, "onLongPress");
		}

		// 双击
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			Log.d(TAG, "onDoubleTap");
			return super.onDoubleTap(e);
		}

	}

}



要点是: 创建一个手势监听器如MyGestureListener继承自SimpleOnGestureListener, 

private class MytGestureListener extends SimpleOnGestureListener 


再用MyGestureListener初始化Detetor对象mDetector,

	// 初始化手势监听器Detector
	private void initDetector() {
		mDetector = new GestureDetectorCompat(MyActivity2.this,
				new MytGestureListener());
	}

然后让mDetector来接替处理手势监听

 // 让GestureDetectorCompat来接替处理
	 @Override
	 public boolean onTouchEvent(MotionEvent event){
	 this.mDetector.onTouchEvent(event);
	 // Be sure to call the superclass implementation
	 return super.onTouchEvent(event);
	 }


三. onFling() 的使用

filing手势在android交互设计中应用非常广泛:电子书的滑动翻页、ListView滑动删除item、滑动解锁等。所以如何检测用户的fling手势是非常重要的。

OnFling的四个参数意思分别为

e1: The first down motion event that started the fling.手势起点的移动事件
e2: The move motion event that triggered the current onFling.当前手势点的移动事件
velocityX: The velocity of this fling measured in pixels per second along the x axis.每秒x轴方向移动的像素
velocityY: The velocity of this fling measured in pixels per second along the y axis.每秒y轴方向移动的像素

说的更简单点就是,鼠标手势相当于一个向量(当然有可能手势是曲线),e1为向量的起点,e2为向量的终点,velocityX为向量水平方向的速度,velocityY为向量垂直方向的速度


if (e1.getX() - e2.getX() > verticalMinDistance && Math.abs(velocityX) > minVelocity)

则上面的语句能知道啥意思了吧,就是说向量的水平长度(滑了有多长)必须大于verticalMinDistance,并且水平方向速度大于minVelocity。


onScroll则与之类似,e1为手势起点事件,e2为手势终点事件,distanceX为e1与e2在x轴的差(带正负),distanceY为e1与e2在y轴的差(带正负)


四. Android中的坐标系统
首先明确一下 android中的坐标系统 :屏幕的左上角是坐标系统原点(0,0),原点向右延伸是X轴正方向,原点向下延伸是Y轴正方向


1、手势处理中常用到的几个函数:

View的getTop()、getBottom(),getLeft(),getRight()得到的坐标是相对父容器视图而言的

motionEvent的getRawX(),getRawY是相对屏幕而言的,getX(),getY()则是相对touch事件的控件而言的

技术分享


2、屏幕的宽和高

为了在屏幕中的合适位置绘制图形,我们需要使用屏幕的宽和高作为参考,来确定绘制图形的位置。要获得屏幕的宽和高,首先从Activity对象中获得WindowManager对象,然后从WindowManager对象中获得Display对象,再从Display对象中获得屏幕的宽和高。
// 获得屏幕的宽和高
WindowManager manger = getWindowManager();
Diaplay diaplay = manager.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();

五、多点触摸事件
参考:http://blog.csdn.net/scarthr/article/details/42437209
获取多个触摸点时,可以调用event.getPointerCount()获取目前的触摸点的个数。要获取某个触摸点,使用event.getX(index)、event.getY(index)获得第index个触摸点的坐标。

 缩放图片

根据两点间的距离的变化就可以检测出两点操作是放大的手势还是缩小的手势:

[java] view plaincopy
  1. package com.example.testtouch;  
  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.ImageView;  
  9. import android.widget.RelativeLayout;  
  10. import android.widget.RelativeLayout.LayoutParams;  
  11.   
  12. public class MainActivity extends Activity {  
  13.   
  14.     private RelativeLayout rl;  
  15.     private ImageView iv;  
  16.     private double lastDistance;  
  17.     private double currentDistance;  
  18.     private double scale = 1;  
  19.   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.activity_main);  
  24.   
  25.         rl = (RelativeLayout) findViewById(R.id.rl);  
  26.         iv = (ImageView) findViewById(R.id.iv);  
  27.   
  28.         rl.setOnTouchListener(new OnTouchListener() {  
  29.   
  30.             @Override  
  31.             public boolean onTouch(View v, MotionEvent event) {  
  32.                 switch (event.getAction()) {  
  33.                 case MotionEvent.ACTION_DOWN:  
  34.                     break;  
  35.                 case MotionEvent.ACTION_MOVE:  
  36.                     LayoutParams lp = (LayoutParams) iv.getLayoutParams();  
  37.                     if (event.getPointerCount() == 2) {  
  38.                         currentDistance = getDistance(  
  39.                                 event.getX(0) - event.getX(1), event.getY(0)  
  40.                                         - event.getY(1));  
  41.                         if (currentDistance - lastDistance >= 5) {  
  42.                             // 放大  
  43.                             scale *= 1.1;  
  44.                             if (scale >= 4) {  
  45.                                 scale = 4;  
  46.                             } else {  
  47.                                 lp.width = (int) (1.1f * iv.getWidth());  
  48.                                 lp.height = (int) (1.1f * iv.getHeight());  
  49.                                 iv.setLayoutParams(lp);  
  50.                             }  
  51.                         } else if (lastDistance - currentDistance >= 5) {  
  52.                             // 缩小  
  53.                             scale *= 0.9;  
  54.                             if (scale <= 1) {  
  55.                                 scale = 1;  
  56.                             } else {  
  57.                                 lp.width = (int) (0.9f * iv.getWidth());  
  58.                                 lp.height = (int) (0.9f * iv.getHeight());  
  59.                                 iv.setLayoutParams(lp);  
  60.                             }  
  61.                         }  
  62.                         lastDistance = currentDistance;  
  63.                     }  
  64.                     break;  
  65.                 case MotionEvent.ACTION_UP:  
  66.                     break;  
  67.                 default:  
  68.                     break;  
  69.                 }  
  70.                 return true;  
  71.             }  
  72.         });  
  73.     }  
  74.   
  75.     /** 
  76.      * 计算两点间距离 
  77.      *  
  78.      * @param x 
  79.      * @param y 
  80.      * @return 
  81.      */  
  82.     private double getDistance(double x, double y) {  
  83.         return Math.sqrt(x * x + y * y);  
  84.     }  
  85. }  

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android 手势监听学习总结

标签:手势

原文地址:http://blog.csdn.net/guige_csdn/article/details/48089723

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!