[英]onInterceptTouchEvent, onTouchEvent only see ACTION_DOWN
我有一个顶级ViewGroup,我称之为SliderView,我想在其中检测滑动。 这主要是有效的,但一个奇怪的失败仍然存在。
SliderView的本质是覆盖onInterceptTouchEvent,一旦用户实际滑动,返回“true”以防止其他视图查看MotionEvent。 这是一段代码:
public class SliderView extends ViewGroup
{
enum MoveState { MS_NONE, MS_HSCROLL, MS_VSCROLL };
private MoveState moveState = MoveState.MS_NONE;
... other code ...
public boolean onInterceptTouchEvent(MotionEvent e)
{
final int action = e.getAction();
switch (action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
moveState = MoveState.MS_NONE;
break;
case MotionEvent.ACTION_MOVE:
if (moveState == MoveState.MS_NONE)
{
if (motion is horizontal)
{
moveState = MoveState.MS_VSCROLL;
return true;
}
else
moveState = MoveState.MS_VSCROLL; // let child window handl MotionEvent
}
else if (moveState == MoveState.MS_HSCROLL)
return true; // don't let children see motion event.
}
return super.onInterceptTouchEvent (e);
}
... other code ...
}
我的理解是我的SliderView(最外面的视图)应该总是接收onInterceptTouchEvent。 在我的一个测试中,顶级子节点是a但是,在下面的情况中,这似乎不是。
当顶级子项是ScrollView时,onInterceptTouchEvent获取ACTION_MOVE并且我的代码执行我想要的操作。 在另一种情况下,顶级子级是LinearLayout,它有时会失败:它总是获得ACTION_DOWN,但只有当用户触摸LinearLayout内的小部件时才获得ACTION_MOVE; 如果触摸空白区域,则仅通过ACTION_DOWN。
我会注意到它的行为就好像在SliderView之外发生了故障情况触摸。 但是,如果是这种情况,为什么我会得到ACTION_DOWN事件?
第二个注意:查看ScrollView的源代码,我看到它检查“inChild”; 我还没弄清楚这是什么以及它可能如何相关。
由于user123321的答案在这里
如果父项具有从onTouchEvent返回“true”的子视图,则仅调用onInterceptTouchEvent。 一旦孩子返回true,父母就有机会拦截该事件
你只需要打电话
requestDisallowInterceptTouchEvent(true);
在父视图上,像这样 -
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch(motionEvent.getActio){
}
return false;
}
来自Android开发人员的参考( http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent) ):
“2. ....此外,通过从onTouchEvent()返回true,您将不会在onInterceptTouchEvent()中收到任何后续事件,并且所有触摸处理必须像on normal一样在onTouchEvent()中进行。”
也许是因为你的onTouchEvent总是返回true ..?
当拦截onTouchEvent时,要正确拦截触摸有两件事要做(其他一切都是默认的)。
在onInterceptTouchEvent()中返回false
@Override public boolean onInterceptTouchEvent(MotionEvent me) { return false; }
在onTouchEvent()中返回true
@Override public boolean onTouchEvent(MotionEvent me) { switch (me.getAction()) { case MotionEvent.ACTION_DOWN: log("MotionEvent.ACTION_DONE"); break; case MotionEvent.ACTION_MOVE: log("MotionEvent.ACTION_MOVE"); break; case MotionEvent.ACTION_CANCEL: log("MotionEvent.ACTION_CANCEL"); userActionDown = false; break; case MotionEvent.ACTION_UP: log("MotionEvent.ACTION_UP"); break; } return true; }
然后,为你的情况(和其他人)。 在onTouchEvent()中完成所有计算,如上所示。 onInterceptTouchEvent()只会为ACTION_DOWN调用一次。 但是,onTouchEvent也会获得ACTION_DOWN事件,你需要在那里返回true,而不是super。
有关onInterceptTouchEvent()的更多信息: http : //developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent (android.view.MotionEvent )
ps - 当你在这里提问时,你也应该写下你想要做的事情的描述。 你可能很有可能找到更好的做事方式。 对于您的导航案例,您正在寻找的真正答案是ViewPager 。 它工作得很好,很容易实现。 您还应该查看Android为开发人员提供的其他一些简单的导航模式: 链接 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.