Android事件分发详解(五)——Touch事件传递验证

来源:互联网 发布:矿物晶体结构数据库 编辑:程序博客网 时间:2024/04/29 09:19

PS:

该系列博客已更新,详情请参见:


http://blog.csdn.net/lfdfhl/article/details/50707742


http://blog.csdn.net/lfdfhl/article/details/50707731


http://blog.csdn.net/lfdfhl/article/details/50707724


http://blog.csdn.net/lfdfhl/article/details/50707721


http://blog.csdn.net/lfdfhl/article/details/50707714


http://blog.csdn.net/lfdfhl/article/details/50707713


http://blog.csdn.net/lfdfhl/article/details/50707700


MainActivity如下:

package cn.c;import android.os.Bundle;import android.app.Activity;import android.view.MotionEvent;/** * Demo描述: * 分析Android事件分发和处理机制 *  *  * 总结: * 1 ViewGroup继承自View *   事件的传递方向为:从最外层(Activity)传递至最内层(某个View) *   事件的消费方向为:从最内层(某个View)传递至最外层(Activity) *   该两个方向是相反的 * 2 ViewGroup中事件处理的流程是: *   dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent *   View中事件处理的流程是: *   dispatchTouchEvent->onTouchEvent * 3 ViewGroup中onInterceptTouchEvent默认值是false *   表示未拦截 *   ViewGroup中onTouchEvent默认值是false *   表示未消费 *   View中onTouchEvent返回默认值是true *   表示已消费 *    *   小结: *   (1) 每一次的ACTION_DOWN和ACTION_MOVE以及ACTION_UP都会引起每一层的dispatchTouchEvent() *       所以:dispatchTouchEvent()的顺序是由上至下的!!!!!!!!!!!!!!! *   (2) 但是每一层的onTouchEvent()就不一定会执行了.比如下层已经消耗掉了事件,那么上层就不会响应onTouchEvent()了. *       所以:onTouchEvent()是从下到上回溯的.当然前提是事件没有被消费的情况下!!!!!!!!!!!!! *  * 在该示例中涉及到三个自定义的View.分别是: * 最外层的布局MyFrameLayout * 内层的布局MyLinearLayout * 最里层的自定义按钮MyButton *  * 现在进行一系列的测试并对现象进行解释 *  * 测试一: * 在MyFrameLayout的dispatchTouchEvent()方法中直接返回false. * 那么可以看到MyFrameLayout的onInterceptTouchEvent()和onTouchEvent()都没有执行. * MyFrameLayout所包含的子View对于Touch事件也当然没有任何的反映. * 其实这样直接返回false是挺残暴的.因为重写了该方法,使得源码中dispatchTouchEvent()方法里的 * 一大堆代码都没有执行,所以它的onInterceptTouchEvent()和onTouchEvent()都没有调用也就没有 * 什么事件的继续分发了. * 因为它直接给Activity返回了false即连ACTION_DOWN事件都没有处理.所以后续的事件比如ACTION_DOWN和ACTION_UP * 都没有资格处理,都是直接由Activity处理了. *  *  * 测试二: * 在MyFrameLayout的dispatchTouchEvent()方法中调用:super.dispatchTouchEvent(ev); * 且返回return super.dispatchTouchEvent(ev); * 在MyFrameLayout的onInterceptTouchEvent()方法中直接返回return true;表示拦截 * 可以看到事件的分发到了MyFrameLayout就停止了,不会向其子View派发. *  * 其余的验证将在下一个例子中给出. *  */public class MainActivity extends Activity {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        System.out.println("===> MainActivity 中调用 onCreate()");        System.out.println("--------------------------------------------------");    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {    System.out.println("===> MainActivity 中调用 dispatchTouchEvent()");System.out.println("===> super.dispatchTouchEvent()默认返回true");System.out.println("--------------------------------------------------");    return super.dispatchTouchEvent(ev);    }@Overridepublic void onUserInteraction() {System.out.println("===> MainActivity 中调用 onUserInteraction()");System.out.println("--------------------------------------------------");super.onUserInteraction();}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_MOVE");break;case MotionEvent.ACTION_UP:System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_UP");default:break;}System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");System.out.println("--------------------------------------------------");return super.onTouchEvent(event);}}


MyFrameLayout如下:

package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;public class MyFrameLayout extends FrameLayout{public MyFrameLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//super.dispatchTouchEvent(ev);System.out.println("外层MyFrameLayout 中调用  dispatchTouchEvent()");System.out.println("super.dispatchTouchEvent()默认返回true 表示继续分发");System.out.println("--------------------------------------------------");return super.dispatchTouchEvent(ev);//return false;}//覆写自ViewGroup@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {System.out.println("外层MyFrameLayout 中调用  onInterceptTouchEvent()");System.out.println("super.onInterceptTouchEvent()默认返回false 表示不拦截");System.out.println("--------------------------------------------------");//return super.onInterceptTouchEvent(ev);return true;}//注意://1 ViewGroup是View的子类//2 ViewGroup中onTouchEvent()方法默认返回的是false@Overridepublic boolean onTouchEvent(MotionEvent event) {//super.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_MOVE");break;case MotionEvent.ACTION_UP:System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_UP");default:break;}System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");System.out.println("--------------------------------------------------");return super.onTouchEvent(event);//return true;}}

MyLinearLayout如下:
package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.LinearLayout;public class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//super.dispatchTouchEvent(ev);System.out.println("内层MyLinearLayout 中调用  dispatchTouchEvent()");System.out.println("super.dispatchTouchEvent()默认返回true 表示继续分发");System.out.println("--------------------------------------------------");//return super.dispatchTouchEvent(ev);return false;}//覆写自ViewGroup@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {//super.onInterceptTouchEvent(ev);System.out.println("内层MyLinearLayout 中调用  onInterceptTouchEvent()");System.out.println("super.onInterceptTouchEvent()默认返回false 表示不拦截");System.out.println("--------------------------------------------------");return super.onInterceptTouchEvent(ev);}//注意://1 ViewGroup是View的子类//2 ViewGroup中onTouchEvent()方法默认返回的是false@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_MOVE");break;case MotionEvent.ACTION_UP:System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_UP");default:break;}System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");System.out.println("--------------------------------------------------");return super.onTouchEvent(event);}}

MyButton如下:
package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.Button;public class MyButton extends Button{public MyButton(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {System.out.println("自定义Button 中调用 dispatchTouchEvent()");System.out.println("super.dispatchTouchEvent默认返回true");System.out.println("--------------------------------------------------");return super.dispatchTouchEvent(event);}//注意://在View的子类中onTouchEvent()方法默认返回的是true@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_MOVE");break;case MotionEvent.ACTION_UP:System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_UP");break;default:break;}System.out.println("super.onTouchEvent()默认返回true");System.out.println("--------------------------------------------------");return super.onTouchEvent(event);}}

main.xml如下:
<!-- 自定义布局中,放置一个自定义控件 --><cn.c.MyFrameLayout     xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <cn.c.MyLinearLayout         android:layout_width="wrap_content"        android:layout_height="wrap_content">   <cn.c.MyButton     android:layout_width="200dip"     android:layout_height="200dip"     android:text="自定义Button"     android:textColor="@android:color/black"   />    </cn.c.MyLinearLayout></cn.c.MyFrameLayout>


0 0
原创粉丝点击