我有一个应用程序需要以不寻常的方式处理事件。
对于我的问题,让我先解释一个简单的案例,即当前Android的事件处理系统不适合我。
假设我有一个 FrameLayout(从现在开始我将调用 ViewSwiper),它添加的所有视图都是 MATCH_PARENT X MATCH_PARENT(我将调用 PageView),它通过翻译实际视图来处理事件并根据方向替换它的移动。这个组件我已经完成并且可以正常工作(使用动画滑动视图)。
但问题出在我在它上面添加的那个 PageView 上,如果 ImageViews 在它的 onTouchEvent 上返回 false,ViewSwiper 将处理这些事件并让另一个 PageView 进入屏幕,但是如果我在上面添加一个 ScrollView,所有事件将被 Scroll 消耗,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;
}
依然没有。