事件分发机制--解决事件冲突的经典方法

外部拦截法

所谓的外部拦截法是指点击事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截,如果不需要此事件就不拦截,这样就可以解决滑动冲突的问题,这种方法比较符合点击事件的分发机制。

外部拦截法需要重写父容器的onInterceptTouchEvent方法,在内部相应的拦截即可,这种方法的伪代码如下:

public boolean onInterceptTouchEvent(MotionEvent event){
	boolean intercepted = false;
	int x = (int) event.getX();
	int y = (int) event.getY();

	switch (event.getAction()){
	case MotionEvent.ACTION_DOWN:{
		intercepted = false;
		break;
	}
	case MotionEvent.ACTION_MOVE:{
		if(父容器需要当前点击事件){
			intercepted = true;
		}else{
			intercepted = false;
		}
		
		break;
	}
	case MotionEvent.ACTION_UP:{
		intercepted = false;
		break;
	}
	default:
		break;
		
	}
	mLastXIntercept = x;
	mLastYIntercept = y;

	return intercepted;

}

内部拦截法

内部拦截法是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器进行处理,这种方法和Android中的事件分发机制不一致,需要配合requestDisallowInterceptTouchEvent方法才能正常工作,使用起来较外部拦截法稍显复杂。

它的伪代码如下,我们需要重写子元素的dispatchTouchEvent方法:

public boolean dispathTouchEvent(MotionEvent event){
	int x = (int) event.getX();
	int y = (int) event.getY();

	switch (event.getAction()){
	case MotionEvent.ACTION_DOWN:{
		parent.requestDisallowInterceptTouchEvent(true);
		break;
	}
	case MotionEvent.ACTION_MOVE:{
		int deltaX = x - mLastX;
		int deltaY = y - mLastY;
		if(父容器需要此类点击事件){
			parent.requestDisallowInterceptTouchEvent(false)
		}
		
		break;
	}
	case MotionEvent.ACTION_UP:{
		break;
	}
	default:
		break;
		
	}
	mLastX = x;
	mLastY = y;

	return super.dispatchTouchEvent(event);
}
上述代码是内部拦截法的典型代码,当面对不同的滑动策略时只需要修改里面的条件即可,其他不需要做改动而已也不能有所改动。

除了子元素需要做处理以为,父容器也要默认拦截除了ACTION_DOWN以外的其他事件,这样子元素调用parent.requestDisallowInterceptTouchEvent(false)方法时,父容器才能继续拦截所需的事件。
为什么父容器不能拦截ACTION_DOWN事件呢? 那是因为ACTION_DOWN事件并不受FLAG_DISALLOW_INTERCEPT这个标记位的控制,所以一旦父容器拦截ACTION_DOWN事件,那么所有的事件都无法传递到子元素中去,这样内部拦截法就无法起作用了。

父容器所做的修改如下:

public boolean onInterceptTouchEvent(MotionEvent event){

	if(event.getAction() == MotionEvent.ACTION_DOWN){
		return false;
	}else {
		return true;
	}
}
就这样

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值