Android onTouchEvent事件

根据用户的触摸判断滑动方向,选择弹出popupWindow 或者dialog ,也可以切换界面,定义切换动画

定义接口:

/**
 * According to the Angle of the sliding range sliding direction
 * @author LanYan
 *
 */
public interface OnEventListener {

	/**
	 * ←
	 */
	void onLeft();
	/**
	 * ↑
	 */
	void onTop();
	/**
	 * →
	 */
	void onRight();
	/**
	 * ↓
	 */
	void onBottom();
	/**
	 *
	 */
	void onNortheast();
	/**
	 *
	 */
	void onNorthwest();
	/**
	 *
	 */
	void onSouthwest();
	/**
	 *
	 */
	void onSoutheast();
	/**
	 * 触摸屏幕
	 */
	void onTouch();
	/**
	 * 事件分发
	 */
	EventType onEventDistribute();
	

方法调用工具类:

import android.view.MotionEvent;
import android.view.View;

public class OnEventTouchFactory {

	private static OnEventTouchFactory mCurrent;
	private static OnEventListener mListener;
	private int mLastEventX;
	private int mLastEventY;
	private EventType mType;
	private int mDistance = 50;
	private double cos;
	private double result;
	private EventType mCurrentType = null;

	public OnEventTouchFactory() {

	}

	public static OnEventTouchFactory getInstance(OnEventListener listener) {
		mListener = listener;
		if (mCurrent == null) {
			mCurrent = new OnEventTouchFactory();
		}
		return mCurrent;
	}

	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		boolean  status=false;
		mListener.onTouch();
		int eventX = (int) event.getX();
		int eventY = (int) event.getY();
		int action = event.getAction();
		if (action == MotionEvent.ACTION_DOWN) {
			mLastEventX = eventX;
			mLastEventY = eventY;
			mCurrentType = mListener.onEventDistribute();
			status=true;
		} else if (action == MotionEvent.ACTION_MOVE) {
			if (mCurrentType == EventType.normal) {
				cos = getAngle(eventX, eventY, mLastEventX, mLastEventY);
				result = getDistance(mLastEventX, mLastEventY, eventX, eventY);
				/**
				 * EeventType: Left ←: [157.5,202.5] Top ↑: [67.5,112.5] Right
				 * →: [337.5,360]&&[0,22.5] Bottom ↓: [247.5,292.5] Northwest :
				 * [112.5,157.5] ┅┅┅┅┅ ┅┅┅┅┅ ┅┅┅┅┅ Southeast : [292.5,337.5] ┇
				 * Southwest : [202.5,247.5] ┇ Northeast : [22.5,67.5] ┇ ┇
				 * VelocityXY  ---------------   ┅┅┅┅┅ ┅┅┅┅┅ ┅┅┅┅┅┅┅┅┅┅
				 * ┅┅┅┅┅┇
				 */

				if ((cos >= 0 && cos <= 22.5) || (cos >= 337.5 && cos <= 360)) {
					mType = EventType.left;
				}

				else if (cos > 22.5 && cos <= 67.5) {
					mType = EventType.nortwest;
				}

				else if (cos >= 67.5 && cos <= 112.5) {
					mType = EventType.top;
				}
				else if (cos > 112.5 && cos < 157.5) {
					mType = EventType.northeast;
				}

				else if (cos >= 157.5 && cos <= 202.5) {
					mType = EventType.right;
				}

				else if (cos > 202.5 && cos < 247.5) {
					mType = EventType.southeast;
				}

				else if (cos >= 247.5 && cos <= 292.5) {
					mType = EventType.bottom;
				}

				else if (cos > 292.5 && cos < 337.5) {
					mType = EventType.southwest;
				}
				status=true;
			}  else if (mCurrentType == EventType.complete) {
				status= false;
			}
		} else if (action == MotionEvent.ACTION_UP) {
			if (mType == EventType.right && result > mDistance) {
				mListener.onRight();
			} else if (mType == EventType.top && result > mDistance) {
				mListener.onTop();
			} else if (mType == EventType.northeast && result > mDistance) {
				mListener.onNortheast();
			} else if (mType == EventType.nortwest && result > mDistance) {
				mListener.onNorthwest();
			} else if (mType == EventType.left && result > mDistance) {
				mListener.onLeft();
			} else if (mType == EventType.southeast && result > mDistance) {
				mListener.onSoutheast();
			} else if (mType == EventType.southwest && result > mDistance) {
				mListener.onSouthwest();
			} else if (mType == EventType.bottom && result > mDistance) {
				mListener.onBottom();
			}
			status=  true;
		}
		return status;
	}

	public double getAngle(int px1, int py1, int px2, int py2) {
		// 两点的x、y值
		int x = px2 - px1;
		int y = py2 - py1;
		double hypotenuse = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
		// 斜边长度
		double cos = x / hypotenuse;
		double radian = Math.acos(cos);
		// 求出弧度
		double angle = 180 / (Math.PI / radian);
		// 用弧度算出角度
		if (y < 0) {
			angle = 180 + (180 - angle);
		} else if ((y == 0) && (x < 0)) {
			angle = 180;
		}
		return angle;
	}

	/**
	 * 获取两点的距离
	 *
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @return
	 */
	public double getDistance(int x1, int y1, int x2, int y2) {
		double d = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
		return Math.sqrt(d);
	}

	public enum EventType {
		left, top, right, bottom, nortwest, southeast, southwest, northeast,
		/**
		 * event不向下分发
		 */
		normal,
		/**
		 * 完全向下分发
		 */
		complete

	}
}

BaseActivity类:

import com.example.base.OnEventTouchFactory.EventType;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;

public abstract class BaseActivity extends Activity implements OnTouchListener, OnEventListener{

	protected Class<?> mLeftClass=null;
	protected Class<?> mRightClass=null;
	protected Class<?> mTopClass=null;
	protected Class<?> mBottomClass=null;

	protected Class<?> mNortheastClass=null;
	protected Class<?> mNorthwestClass=null;
	protected Class<?> mSoutheastClass=null;
	protected Class<?> mSouthwestClass=null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setTheme();
		setContentView(getLayoutResID());
		configClass();
		initialization();
	}

	public abstract int getLayoutResID();
	public void setTheme(){

	}
	public void configClass(){

	}
	public void initialization(){

	}

	/***********************************onTouch*********************************************/

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		if(OnEventTouchFactory.getInstance(this).onTouch(v, event)){
			return true;
		}

		return false;
	}

	@Override
	public void onLeft() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onTop() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onRight() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onBottom() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onNortheast() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onNorthwest() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onSouthwest() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onSoutheast() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onTouch() {
		// TODO Auto-generated method stub

	}

	@Override
	public EventType onEventDistribute() {
		// TODO Auto-generated method stub
		return EventType.normal;
	}
	/***********************************Method*********************************************/
	public void startActivity(Class<?> cls){
		Intent intent=new Intent();
		intent.setClass(this, cls);
		startActivity(intent);
	}
	public void startActivity(Class<?> cls,boolean isFinish){
		Intent intent=new Intent();
		intent.setClass(this, cls);
		startActivity(intent);
		if(isFinish){
			finish();
		}
	}

	public void startActivityWithAnimation(Class<?> cls,int enterAnim,int exitAnim){
		Intent intent=new Intent();
		intent.setClass(this, cls);
		startActivity(intent);
		overridePendingTransition(enterAnim, exitAnim);
	}

	public void startActivity(Class<?> cls,boolean isFinish,int enterAnim,int exitAnim){
		Intent intent=new Intent();
		intent.setClass(this, cls);
		startActivity(intent);
		if(isFinish){
			finish();
		}
		overridePendingTransition(enterAnim, exitAnim);
	}
	public void ShowSToast(String message){
		Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
	}
	public void ShowLToast(String message){
		Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
	}
}

测试Activity类:

import android.text.method.ScrollingMovementMethod;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.base.BaseActivity;
import com.example.base.OnEventTouchFactory.EventType;

public class MainActivity extends BaseActivity {

	@Override
	public int getLayoutResID() {
		// TODO Auto-generated method stub
		return R.layout.activity_main;
	}

	@Override
	public void configClass() {
		// TODO Auto-generated method stub
		super.configClass();
	}

	@Override
	public void initialization() {
		// TODO Auto-generated method stub
		super.initialization();
		RelativeLayout parent=(RelativeLayout)findViewById(R.id.parent);
		TextView child=(TextView)findViewById(R.id.child);

		child.setMovementMethod(ScrollingMovementMethod.getInstance());
	    parent.setOnTouchListener(this);
	}
	@Override
	public void onRight() {
		// TODO Auto-generated method stub
		super.onRight();
		ShowSToast("right");
	}
	@Override
	public void onTop() {
		// TODO Auto-generated method stub
		super.onTop();
		ShowSToast("top");
	}
	@Override
	public void onLeft() {
		// TODO Auto-generated method stub
		super.onLeft();
		ShowSToast("left");
	}
	@Override
	public void onBottom() {
		// TODO Auto-generated method stub
		super.onBottom();
		ShowSToast("bottom");
	}
	@Override
	public void onNortheast() {
		// TODO Auto-generated method stub
		super.onNortheast();
		ShowSToast("northeast");
	}
	@Override
	public void onNorthwest() {
		// TODO Auto-generated method stub
		super.onNorthwest();
		ShowSToast("northwest");
	}
	@Override
	public void onSoutheast() {
		// TODO Auto-generated method stub
		super.onSoutheast();
		ShowSToast("southeast");
	}
	@Override
	public void onSouthwest() {
		// TODO Auto-generated method stub
		super.onSouthwest();
		ShowSToast("southwest");
	}
	@Override
	public void onTouch() {
		// TODO Auto-generated method stub
		super.onTouch();
	}

	@Override
	public EventType onEventDistribute() {
		// TODO Auto-generated method stub
		return super.onEventDistribute();
	}

}

BaseActivity 类实现了OnEventListener,并将该类抽象,那么在子类里面需要手势操作 绑定Touch事件即可,通过OnEventListener的回调函数处理手势操作

这是简单的手势操作,复杂点的(比如onTouch的冲突)需要涉及到 类:View ViewGroup Activity  ,涉及到的方法:dispatchTouchEvent(事件分发)  onInterceptTouchEvent(事件拦截) onTouch onTouchEvent..Activity 里面不含onInterceptTouchEvent方法

时间: 2024-11-07 17:25:30

Android onTouchEvent事件的相关文章

从源码角度带你分析 Android View 事件分发 dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程(一)

关于Android View 事件分发过程的文章网络上可以搜到一把大,这里贴一篇代码性的文章,作者也是个牛人:Android事件分发机制完全解析,带你从源码的角度彻底理解(上). 虽然讲的很好,但是看完之后还是感觉有那么点一知半解,于是自己花了点时间从源码研究android 触摸事件分发流程,以下内容仅仅个人理解,如有差错希望指出. 我们先从一个例子看起,先重写一个MyButton 继承Button,代码如下: public class MyButton extends Button { pub

Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)

1 背景 还记得前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事件疑惑吗?当时说了,在那一篇咱们只讨论View的触摸事件派发机制,这个疑惑留在了这一篇解释,也就是ViewGroup的事件派发机制. PS:阅读本篇前建议先查看前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>,这一篇承接上一篇. 关于View与ViewGroup的区别在前一篇的A

Android Touch事件传递机制解析

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵.. android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发TouchEvent 2)public boolean onInterceptTouchEvent(MotionEv

Android touch 事件传递机制

前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事件进行拦截.这个时候我们就需要明白android touch 事件传递机制, (2)以前很多时候比较模糊,也许是网上看到也有很多事件传递的相关文章,但我看着头晕,解释不彻底,有的说得一半,总算不满足不满意,于是据我自己的理解来彻底的来整理下具体的是怎么个传递方式,分享给大家,希望大家看到有什么不对的

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~ MyButton [java] view plain copy package com.example.zhy_event03; import android.content.Context; import andr

【转】Android Touch事件传递机制解析

原文地址:http://www.cnblogs.com/runssnail/p/4250549.html 说明:本文在原文地址上有所改动 一.小故事 在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给了自己组员(程序员) 程序员:分派给了自己带的实习生. 实习生:好苦逼,无法分派,怎么办啊?只能自己干了 但是实习生能不能做好,有两种情况了. 情况一:

Android Touch事件传递机制解析 (推荐)

最近新闻列表里的下拉 down up  move 等等让我十分头疼 ,无意间看到了一篇非常不错的帖子,转载如下: 开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵.. android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发T

Android Touch事件传递机制详解 上

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 最近总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,以前也花时间学习过Android Touch事件的传递机制,可以每次用起来的时候总是忘记了,索性自己总结一下写篇文章避免以后忘记了,其实网上关于Touch事件的传递的文章真的很多,但是很少有系统性的,都是写了一个简单的demo运行了一下,对于我们了解Android Touch事件基本上没有任何帮助. 今

android Touch事件传递小结

这次还是先贴上测试代码吧.. 主布局文件是个三层结构,最外层和中间层都是LinearLayout的子类,里层是个TextView: <com.example.touchevent.OutterLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/o