1:简述
所谓的android中的事件冲突:就是view1拦截消耗了本是应该view2消费的事件,前提触摸点在view1和view2范围之内!那么我们必须进行简单了解一下:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent:三个方法:
是ViewGroup和View对象共有的方法,是事件分发机制执行的方法,简单叙述一下事件分发机制:
{1}首先父容器ViewGroup在同一个事件序列的MotionEvent.ACTION_DOWN事件中,进行判断是否自身需要拦截:主要通过onInterceptionTouchEvent方法判断是否需要自己拦截,如果拦截:那么如果OnTouchListener设置,进行调用自身的onTouchListener方 法,否则进行调用onTouchEvent方法!
{2}继而会向下传递给子节点View,进行判断如果OnTouchListener设置,进行调用自身的onTouchListener方法,如果onTouchListener返 回true那么表示消耗了该事件,否则进行调用 onTouchEvent方法,如果onTouchEvent返回true,代表事件已消耗,否则上传给父容器!
是ViewGroup父容器的方法,而view对象是没有的!父容器主要在该方法里进行是否需要拦截事件的业务逻辑处理!如果在某个事件操作中,判断出返回true,那么会交给自身的OnTouchListener和OnTouchEvent方法!该执行有先后顺序,如果onTouchListener返回true那么表示消耗了该事件,否则进行调用 onTouchEvent方法,如果onTouchEvent返回true,代表事件已消耗,否则上传给父容器!
- 实例:ViewPager和ScrollView事件冲突
在一个页面中整体用ScrollView包裹可以竖向的滑动,头部是一个ViewPager的图片轮播相册,在横向滑动轮播相册时,出现滑动不灵敏:在横向滑动时,整体的界面会竖向偏移.显然在横向滑动时,ScrollView拦截了某些事件!
解决方案:自定义一个MyScrollView复写onInterceptTouchEvent:在按下MotionEvent.ActionDown事件时:交给父容器进行处理(如果不交给父容器处理,拦截效果失败).在MotionEvent.ActionMove事件时,判断横向滑动时,进行拦截事件,交给子容器ViewPager进行处理.
代码
public class HorizontalScrollView extends ScrollView {
boolean isIntercept;
public HorizontalScrollView(Context context) {
super(context);
}
public HorizontalScrollView(Context context,
AttributeSet attrs,int defStyle) {
super(context, attrs, defStyle);
}
public HorizontalScrollView(Context context,
AttributeSet attrs) {
super(context, attrs);
}
float startX,startY,moveX,moveY,lastMoveX,lastMoveY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch(ev.getAction()){
case MotionEvent.ACTION_DOWN:
isIntercept=true;
startX=ev.getX();
startY=ev.getY();
case MotionEvent.ACTION_MOVE:
if(moveX==0 && moveY==0){
lastMoveX=ev.getX();
lastMoveY=ev.getY();
}else{
lastMoveX=moveX;
lastMoveY=moveY;
}
moveX=ev.getX();
moveY=ev.getY();
if(Math.abs(startX-moveX)>
Math.abs(startY-moveY)){
isIntercept=false;
}else{
isIntercept=true;
}
break;
case MotionEvent.ACTION_UP:
break;
}
if(isIntercept){
return super.onInterceptTouchEvent(ev);
}else{
return isIntercept;
}
}
}
- 实例:ScrollView和RecyclerView事件冲突
整体的界面用ScrollView包裹,页面中用RecyclerView进行显示列表数据,如果滑动到RecyclerView的列表数据焦点范围内,导致ScrollView不拦截事件,页面的竖直方向就没有惯性滑动了!
解决方法:自定义一个VerticalScrollView竖向的ScrollView,在竖直方向上拦截事件!
public class VerticalScrollView extends ScrollView{
public VerticalScrollView(Context context) {
super(context);
}
public VerticalScrollView(Context context,
AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollView(Context context,
AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
float startX,startY;
float moveX,moveY;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX=event.getRawX();
startY=event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
moveY=event.getRawY();
moveX=event.getRawX();
if(Math.abs(moveY-startY)>
Math.abs(moveX-startX)){
return true;
}
break;
}
return super.onInterceptTouchEvent(event);
}
}