Android基础之Touch事件和手势处理
来源:互联网 发布:linux 删除路由表 编辑:程序博客网 时间:2024/06/03 21:52
Touch事件和手势处理
- Touch事件
·Touch事件:用户的手势操作
·Android设备中的应用程序主要依赖于用户的各种手势操作实现交互,常见的手势操作有:单击、长按,滑动。
onTouchEvent()方法
·在view类中定义了onTouchEvent()方法,用于处理Touch事件,View的每个子类都可以重写该方法,以决定该view如何处理Touch事件,方法签名为:
- public boolean onTouchEvent(MotionEvent event)
·在Activity类中也定义了onTouchEvent()方法,则每个Activity的子孙类都可以重写该方法,用于决定当前Activity中如何处理Touch事件,该方法签名与View类定义的onTouchEvent()方法的签名完全相同。
View.OnTouchListener接口
·在View类中定义了setOnTouchListener()方法,用于为View对象指定Touch事件处理监听器,该方法的参数类型是View.OnTouchListener接口,接口中的抽象方法签名为:
- boolean onTouch(View v ,MotionEvent event);
MotionEvent类
无论View类或Activity类中定义的onTouchEvent()方法,或View类中的OnTouchListener接口的抽象方法中,都使用了MotionEvent的对象作为参数,该类的常用方法有:
·public final int getAction() //用于获取Touch事件是属于哪类型的事件(如:按下或者离开)
·public final float getX() //当前正在操作的手触碰到频幕后,对应到点的X轴的坐标
·public final float getX(int pointerIndex) //多点触碰
·public final float getY() //当前正在操作的手触碰到频幕后,对应到点的Y轴的坐标
·public final float getY(int pointerIndex)
·MotionEvent类中定义了一系列的常量,用于标识Touch操作的类型,亦可用于尝试匹配getAction()方法的返回值,常用的常量有:
·public static final int ACTION_DOWN //当手刚好按到屏幕的那一刻
·public static final int ACTION_UP //手刚好从屏幕上离开的那一刻
·public static final int ACTION_MOVE //手按下屏幕正在移动时处理Touch事件方法的返回值
·无论View类或Activity类中定义的onTouchEvent()方法,或View类中的OnTouchListener接口的抽象方法,各方法的返回值均是boolean类型。
·由于同一次的某个操作可能导致多个处理Touch事件的方法被回调,当方法的返回值被指定为true时,表示当前方法已“消费”该事件,则后续尝试处理该Touch事件的方法不会被回调,如果返回值被指定为false时,则后续尝试处理该Touch事件的方法会正常执行。处理Touch事件:
·View.onTouchEvent()
·Activity.onTouchEvent()
·View.setOnTouchListener()简单的自定义View
·当需要自定义View时,需要创建新的Java类,继承自View或者View的子孙类。
·由于View没有无参数的构造方法,则自定义View需要显示的创建带参数的构造方法:
·如果希望在程序中使用new关键字创建自定义view的对象,则必须显示的创建带1个参数的构造方法;
·如果希望在res\layout\下的布局文件中使用自定义View设计布局,则必须显示的创建带2个参数或者带3个参数的构造方法。Touch事件的派发和处理逻辑
·在Android系统中,视图系统大致分为View与ViewGroup:
- View是一般独立显示了具体内容的控件,例如:TextView,ImageView等;
- ViewGroup是用于承载其他控件的,例如RelativeLayout、ListView等。
·当出现Touch事件时,需要明确是由View或是ViewGroup处理事件。·在Android系统中,视图系统中存在3个方法处理Touch事件相关逻辑:
- public boolean dispatchTouchEvent(MotionEvent ev):处理事件分发;
- public boolean onInterceptTouchEvent(MotionEvent ev): 处理事件拦截;
- public boolean onTouchEvent(MotionEvent ev): 处理事件响应。
·由于简单的View对象不存在子级控件,所以并不存在事件拦截的操作,即没有OnInterceptEvent()方法。·每个ViewGroup在接收到事件后,默认遵循“分发 –> 拦截 –> 处理”的流程执行相关的方法。
·在默认情况下:
- 事件分发:“隧道式”,即从最外层控件依次传递,直至最内层子级控件,也就是说,越靠近根节点,分发的权力越大。
- 事件处理:“冒泡式”,即从最内层子级控件开始处理,直到最外层的控件。事件分发(dispatchTouchEvent)的逻辑如下:
- 当返回值true时,由dispatchTouchEvent()直接消费,事件将不再传递,即不会拦截,相应,更不会向分发到其它控件;
- 当返回值为false时:
·如果事件是Activity获取的,则由Activity的onTouchEvent()消费;
·如果事件是父控件的,则由父控件的onTouchEvent()消费。事件拦截(onInterceptTouchEvent)的逻辑如下:
- 当返回值为true时,表示当前控件拦截事件,且当前控件的onTouchEvent()会被执行,事件并不会向后传递到其他控件;
- 当返回值为false时,表示不拦截,即放行,事件将交给子级控件去分发(即子级控件的dispatchTouchEvent()方法将被执行)。事件响应(onTouchEvent)的逻辑如下:
- 当返回值为true时,表示当前控件已消费事件,则整个事件处理过程结束;
- 当返回值为false时,表示当前控件未消费事件(可能开发人员已编写程序响应,但只要返回值为false,就不表示消费了该事件),将由父级控件继续响应,即父级控件的onTouchEvent()方法会被调用。特殊的单击事件
·在Android系统中,关于屏幕上的操作都属于Touch操作,例如单击则是由:“按下 -> 弹起”这2种动作组合完成的。
·单击事件是直接消费事件,因此,当点击界面上的Button时,一定是由Button处理事件,且其父级控件无法对单击事件进行相应。GestureDetector
一个activity中new一个GestureDetector之后,里面会实现一下的方法:
onSingleTapUp
onShowPress
onScroll
onLongPress
onFling
onDown
说一下这些方法都是由那些MotionEvent触发的
今天的项目用到了onSingleTapUp和onShowPress和onLongPress和onFling;
1、onSingleTapUp、onSingleTapConfirmed
用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
这个事件执行的顺序是onDown-》onShowPress-》onSingleTapUp
区别:
点击一下非常快的(不滑动)Touchup:onDown->onSingleTapUp->onSingleTapConfirmed
点击一下稍微慢点的(不滑 动)Touchup:onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
2、onShowPress
用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
它与onDown()的区别,强调的是没有松开或者拖动的状态
3、onDown
而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间(这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。
4、onLongPress
用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
这个事件执行的顺序是onDown-》onShowPress-》onLongPress
5、onFling
用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE,1个ACTION_UP触发
6、onScroll
Touch了 滑动时触发。
- 示例:
activity:
package com.example.touch_event;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;public class MainActivity extends Activity { private String Tag = "com.example.touch_event"; private TouchView touchView; private GestureDetector gestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); touchView = (TouchView) findViewById(R.id.touchView1); gestureDetector = new GestureDetector(new InnerGestureDetector()); touchView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d(Tag , "setOnTouchListener.onTouchEvent--->ACTION_DOWN"); break; case MotionEvent.ACTION_UP: Log.d(Tag, "setOnTouchListener.onTouchEvent--->ACTION_UP"); break; case MotionEvent.ACTION_MOVE: Log.d(Tag, "setOnTouchListener.onTouchEvent--->ACTION_MOVE"); break; } return gestureDetector.onTouchEvent(event); } }); } private class InnerGestureDetector implements GestureDetector.OnGestureListener{ //用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发 @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } //用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE,1个ACTION_UP触发 @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; } //用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发 @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } //Touch了 滑动时触发 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } //用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发 @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } //用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发 @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } } private long artionDownTime; private float artionDownX,artionDownY; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: artionDownTime = System.currentTimeMillis(); artionDownX = event.getX(); artionDownY = event.getY(); break; case MotionEvent.ACTION_UP: if(System.currentTimeMillis() - artionDownTime < 500){ if(Math.abs(event.getX() - artionDownX) < 30 && Math.abs(event.getY() - artionDownY) < 30){ Log.d(Tag, "单击!!!..."); } } break; } /*switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(Tag , "MainActivity.onTouchEvent--->ACTION_DOWN"); break; case MotionEvent.ACTION_UP: Log.i(Tag, "MainActivity.onTouchEvent--->ACTION_UP"); break; case MotionEvent.ACTION_MOVE: Log.i(Tag, "MainActivity.onTouchEvent--->ACTION_MOVE"); break; }*/ return gestureDetector.onTouchEvent(event); }}
TouchView:
package com.example.touch_event;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.TextView;public class TouchView extends TextView{ public TouchView(Context context) { super(context); // TODO Auto-generated constructor stub } public TouchView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public TouchView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { /*switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.w(Tag, ""); break; case MotionEvent.ACTION_UP: Log.w(Tag, ""); break; case MotionEvent.ACTION_MOVE: Log.w(Tag, ""); break; }*/ return super.onTouchEvent(event); }}
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <com.example.touch_event.TouchView android:id="@+id/touchView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#000000" android:textSize="24sp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="TouchView" /></RelativeLayout>
- Android基础之Touch事件和手势处理
- Android的Touch事件处理和手势
- android之Touch事件处理机制
- android之touch事件处理机制
- android touch 事件分发和处理
- android touch事件处理
- android touch事件处理
- Android Touch事件处理
- Android: Android Touch事件处理
- Android Touch事件处理机制
- Android touch事件处理流程
- Android中的Touch事件处理
- Android中的Touch事件处理
- Android中的Touch事件处理
- Android的Touch事件处理
- Android Touch事件处理机制
- Android中的Touch事件处理
- Android 共同处理touch事件
- LeetCode70. Climbing Stairs
- Autolayout自动布局3
- 图片加载框架之Picasso
- Python异常处理
- Power of Three
- Android基础之Touch事件和手势处理
- Projects:Python项目大集合
- MonoDevelop 打开App异常问题
- HDU1284 【DP入门之完全背包】
- 1026. 程序运行时间(15)
- 对称矩阵、Hermite矩阵、正交矩阵、酉矩阵、奇异矩阵、正规矩阵、幂等矩阵
- android访问网页
- 字符编码笔记:ASCII,Unicode和UTF-8
- 利用zbar实现条形码扫描