触摸事件分发
几个重要的方法
-
触摸事件分发:定义在
View
中@Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); }
- 这个方法一般不去处理。
- 这个方法内部调用了事件打断和事件处理方法
- 本次触摸事件中控件或者其子控件处理了事件就返回
true
-
触摸事件打断:定义在
ViewGroup
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev); }
- 打断触摸事件的传递(父控件收回子控件对触摸事件的处理权)
- 不能打断自己处理的事件
- 打断子控件对事件的处理的时候,子控件会调用
action_cancel
,子控件可能需要对这个事件进行处理
-
触摸事件处理:定义在
View
@Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }
- 是否处理只在
action_down
时有效:如果在action_down
的时候返回true
表示它要处理本次所有的触摸事件 - 内部调用
onTouch()
,如果用户实现了setOnTouchListener
监听,它的返回值就是onTouchEvent的返回值
- 是否处理只在
触摸事件处理(U型):事件从父控件-->子控件分发,事件处理从子控件-->父控件直到被处理;
事件冲突处理例子
SlidingPaneLayout布局里面子控件有ViewPager的时候,SlidingPaneLayout打断ViewPager的滑动事件处理
解决方案一:ViewPager添加setOnTouchListener
pager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// v就是viewpager
ViewGroup parent = (ViewGroup) v.getParent();
float x = event.getX();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x < parent.getWidth() / 5) { // 不要写定值
parent.requestDisallowInterceptTouchEvent(false); // 打断,收回子控件对触摸事件的处理权,这个时候可以拉出SlidingPaneLayout
} else {
parent.requestDisallowInterceptTouchEvent(true); // 不被打断,滑动操作ViewPager
}
}
return false;
}
});
解决方案二:自定义SlidingPaneLayout
public class PagerAdapter extends android.support.v4.view.PagerAdapter {
// 重写打断方法
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
flag = isOpen() || (ev.getX() < getWidth() / 5);
}
return flag && super.onInterceptTouchEvent(ev);
}
}
网友评论