您的位置:首页 > 移动开发 > Android开发

Android Touch事件分发机制总结

2016-09-22 15:22 459 查看
虽然时常写自定义控件,但对Touch事件分发机制只是简单的理解,这次深入研究了它。网上很多这种文章都介绍得太简单,甚至错误。最近也研究了NestedScrolling,顺便说句,传统的Touch机制也能将事件回传给父Layout,有些介绍NestedScrolling的文章说传统的Touch机制不可以,这是错误的。

要点都在下面的注释里:

MyLinearLayout.java
package com.customview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

/**
* 一、dispatchTouchEvent
* 1、return super.dispatchTouchEvent(event);
* dispatchTouchEvent会处理ACTION_DOWN,然后分给onInterceptTouchEvent
* 是否处理余下的事件ACTION_MOVE和ACTION_UP,看onInterceptTouchEvent和onTouchEvent
*
* (1)onInterceptTouchEvent
* onInterceptTouchEvent会处理ACTION_DOWN
* 是否处理余下的事件,看自己和onTouchEvent
*
* ——false,与super.onInterceptTouchEvent(event)等同,
* 不拦截,会处理余下的事件,然后分发事件给子View,不会给onTouchEvent
*
* ——true,拦截,不分发事件给子View,给onTouchEvent(也即只交事件给自己),是否处理余下事件看onTouchEvent
*
*
* (2)onTouchEvent
* ——false,只会处理ACTION_DOWN
* ——true,与super.onTouchEvent(event)几乎等同,会处理完整事件
*
*
* 处理完整的ACTION事件按此顺序(如果都处理的话):ACTION_DOWN——>ACTION_MOVE(一个或多个)——>ACTION_UP
* 处理ACTION事件的方法按此顺序(如果都处理的话):
* dispatchTouchEvent——>onInterceptTouchEvent(return false)——>子View
* (return true)——>onTouchEvent
*
*
* 2、return true
* dispatchTouchEvent会处理完整事件,不会给onInterceptTouchEvent和onTouchEvent,更不会给子View
*
* 3、return false
* dispatchTouchEvent只会处理ACTION_DOWN,不会给onInterceptTouchEvent和onTouchEvent,更不会给子View
*
*
*
*/

public class MyLinearLayout extends LinearLayout {
private final String TAG = "MyLinearLayout";

public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:
Log.e(TAG, "dispatchTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "dispatchTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "dispatchTouchEvent action:ACTION_UP");
break;
}
return super.dispatchTouchEvent(event);
// return true;
// return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onInterceptTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onInterceptTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onInterceptTouchEvent action:ACTION_UP");
break;
}
return super.onInterceptTouchEvent(event);
// return true;
// return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "---onTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "---onTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "---onTouchEvent action:ACTION_UP");
break;
}
return true;
// return super.onTouchEvent(event);
// return false;
}

}
MyTextView.java

package com.customview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
/**
* 一、dispatchTouchEvent
* 1、return super.dispatchTouchEvent(event);
* dispatchTouchEvent会处理ACTION_DOWN,然后分给onTouchEvent
* 是否处理余下的事件ACTION_MOVE和ACTION_UP,看onTouchEvent
*
* (1)onTouchEvent
* ——false,与super.onTouchEvent(event)几乎等同,只会处理ACTION_DOWN,然后会回给父Layout作处理:
*<1> 如果父的onTouchEvent是return true或者super.onTouchEvent(event),
*则父的onTouchEvent先处理一下ACTION_DOWN,然后由父的dispatchTouchEvent和onTouchEvent处理ACTION_MOVE和ACTION_UP
*<2> 如果父的onTouchEvent是return false
*则父的onTouchEvent只会处理ACTION_DOWN,余下事件不作处理
*
* ——true,会处理完整事件,不回给父Layout
*
* 2、return true
* dispatchTouchEvent会处理完整事件,不会给onTouchEvent,也不回给父Layout
*
* 3、return false
* dispatchTouchEvent只会处理ACTION_DOWN,不会给onTouchEvent,然后会回给父Layout作处理:
*<1> 如果父的onTouchEvent是return true
*则父的onTouchEvent先处理一下ACTION_DOWN,然后由父的dispatchTouchEvent和onTouchEvent处理ACTION_MOVE和ACTION_UP
*<2> 如果父的onTouchEvent是return false或者super.onTouchEvent(event),
*则父的onTouchEvent只会处理ACTION_DOWN,余下事件不作处理
*
*
*/
public class MyTextView extends TextView {

private final String TAG = "MyTextView";

public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
break;
}
return super.dispatchTouchEvent(event);
// return false;
// return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "---onTouchEvent action:ACTION_UP");
break;
}

// return true;
return false;
// return super.onTouchEvent(event);
}

}

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.customview.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >

<com.customview.MyTextView
android:id="@+id/tv"
android:layout_width="200px"
android:layout_height="200px"
android:background="#00ffee"
android:gravity="center"
android:text="点我"
android:textColor="#0000FF"
android:textSize="30sp" />

</com.customview.MyLinearLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: