Android事件传递机制

1、跟touch事件相关的三个方法:

用来分派event

public boolean dispatchTouchEvent(MotionEvent ev);


用来拦截event

public boolean onInterceptTouchEvent(MotionEvent ev);


用来处理event

public boolean onTouchEvent(MotionEventev);





2、三个方法的用法:

diapatchTouchEvent():用来分派事件,其中调用了onInterceptTouchEvent()onToucEvent(),一般不重写该方法。


OnInterceptTouchEvent():用来拦截事件。ViewGroup类中的源码实现就是{returnfalse;},表示不拦截该事件,事件将向下传递(传递给其子View);若手动重写该方法,使其返回true则表示拦截事件,事件将终止向下传递,事件有当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法。


OnTouchEvent():用来处理事件。返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);返回false表示不能处理,则把事件传递给其父ViewonTouchEvent()方法处理。


下面根据自己写的一个Demo进行具体的分析:

下面是该demo的布局效果图:







其代码如下:

Activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <com.example.scrolllayouttest.MainLinearLayout
        android:layout_width="400dp"
        android:layout_height="400dp"
        android:background="#ffcc00">
        
        <com.example.scrolllayouttest.SubLinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#00cc00">
            
        </com.example.scrolllayouttest.SubLinearLayout>
    </com.example.scrolllayouttest.MainLinearLayout>

</LinearLayout>

Activity中的监听代码:

@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", " ActivityOne onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "ActivityOne onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "ActivityOne onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	}

MainLinearLayout的监听代码:

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
//		return true;
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	//	return true;
	}

SubLinearLayout的监听代码:


@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	//	return true;
	}

情景一:

可以看到现在所有的事件的传递函数都是默认返回super.onInterceptTouchEvent(ev)或者返回super.onTouchEvent(event);就是表示都不拦截,不处理事件。

运行程序,查看打印的Log信息:


可以分析,按下的ACTION_DOWN事件先是传递到MainLinearLayoutonInterceptTouchEvent中判断是否进行拦截,不拦截则会传递子ViewSubLinearLayout中,在SubLinearLayout中的onInterceptTouchEvent判断是否拦截,不拦截。由于传递到了最后一个View了,所以先由最后一个ViewonTouchEvent进行判断,是否处理该事件,由于是SubLinearLayout返回super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于MainLinearLayoutonTouchEvent返回的是super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于没有子View消费该事件,所以事件最后传递到ActivityonTouchEvent中,由Activity进行处理该事件。

情景二:


MainLinearLayout中的监听代码改为:

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
	//	return super.onInterceptTouchEvent(ev);
		return true;
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
    <span style="font-family:Droid Sans;">//</span>          return super.onTouchEvent(event);
		return true;
	}

表示MainLinearLayout拦截该事件(在onInterceptTouchEvent中返回true),并且处理该事件(在onTouchEvent中返回true)。



根据其Log,可以分析,事件先是传递到MainLinearLayoutonInterceptTouchEvent中判断是否需要拦截该事件,由于是返回true,所以MainLinearLayout拦截了事件,事件就交由MainLinearLayoutonTouchEvent进行事件的处理了;在MainLinearLayoutonTouchEvent中,由于是返回了true,表示能处理该事件,所以后面的ACTION_MOVE,ACTION_UP都交由MainLinearLayoutonTouchEvent来处理。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值