我有一个应用程序需要以一种不寻常的方式处理事件。
对于我的问题,让我先解释一个简单的例子,Android当前的事件处理系统不适合我。
假设我有一个框架布局(我将调用ViewSwiper从现在起),所有的视图添加在它是MATCH_PARENT X MATCH_PARENT(我将调用PageView),它的处理事件翻译实际视图和替换它基于移动的方向。这个组件我已经完成并正常工作(使用动画滑动视图)。
但问题是我在上面添加的PageView,在ImageViews的onTouchEvent返回false的情况下,ViewSwiper将处理事件,让另一个PageView进入屏幕,但如果我添加一个ScrollView,所有的事件将被消耗的滚动和ViewSwiper将没有机会取代PageView。
所以我发现返回false的onTouchEvent的ScrollView父可以假设它的事件,我写了ScrollView的这个子类来测试它:
public class ScrollViewVertical extends ScrollView {
public ScrollViewVertical(Context context) {
super(context);
setOverScrollMode(OVER_SCROLL_ALWAYS);
setVerticalScrollBarEnabled(false);
}
public boolean onTouchEvent(MotionEvent evt) {
super.onTouchEvent(evt);
return false;
}
}
但返回false使任何进一步的事件被分派给父,但我需要这些事件的垂直滚动,所以我有想法返回false只有当用户是水平移动,这就是我的代码看起来像:
public class ScrollViewVertical extends ScrollView {
private MovementTracker moveTracker;
public ScrollViewVertical(Context context) {
super(context);
setOverScrollMode(OVER_SCROLL_ALWAYS);
setVerticalScrollBarEnabled(false);
moveTracker = new MovementTracker();
}
public boolean onTouchEvent(MotionEvent evt) {
if (moveTracker.track(evt))
if (moveTracker.getDirection() == Direction.HORIZONTAL)
return false;
return super.onTouchEvent(evt);
}
}
PS: MovementTracker将在track()发生一些事件后返回true,并告诉用户在哪个方向移动。
但是在这种情况下,ScrollView继续接收事件,因为它在第一个事件上返回true。
关于如何处理ViewSwiper上的事件,当它的子返回false(即使返回一些true)的任何想法。
PS:如果需要,我可以给出更多的信息,也可以接受不同的解决方案。
根据答案,我尝试了以下方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
onTouchEvent(ev);
return intercept;
}
public boolean onTouchEvent(MotionEvent evt) {
boolean x = super.onTouchEvent(evt);
if (moveTracker.track(evt)) {
intercept = moveTracker.getDirection() != Direction.VERTICAL;
if (!intercept)
getParent().requestDisallowInterceptTouchEvent(false);
}
return x;
}
还没有。
在scrollview的onTouchEvent()
中试试
//if (evt.getAction() == MotionEvent.ACTION_MOVE) {
if (moveTracker.track(evt)){
if (moveTracker.getDirection() == Direction.VERTICAL){
//Or the direction you want the scrollview keep moving
getParent().requestDisallowInterceptTouchEvent(true);
}
}
return true;
更新请尝试以下自定义滚动视图
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return false;
}
没有其他
这样,我假设MotionEvent将在两个视图上执行。因为它们不冲突(一个是垂直的,另一个是水平的)这就可以了
根据weakwire的回答,我得出了以下解决方案:
在ViewSwiper @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(!super.dispatchTouchEvent(ev))
onTouchEvent(ev);
return true;
}
在ScrollHorizontal上,当我不再需要dispatchTouchEvent时,我返回false