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。在我的一个测试中,顶层子项是一个ScrollView时,onInterceptTouchEvent会得到ACTION_MOVE并且我的代码会按预期执行。但在另一种情况下,顶层子项是LinearLayout时,有时会失败:它总是会得到ACTION_DOWN,但只有当用户触摸LinearLayout内的小部件时才会得到ACTION_MOVE;如果触摸空白区域,则只会传递ACTION_DOWN。
我注意到它的行为就好像失败的情况触摸发生在SliderView之外。但是,如果是这样,为什么我会收到ACTION_DOWN事件呢?
第二个注意事项:查看ScrollView的源代码,我看到它检查了“inChild”;我还没有弄清楚那是做什么的,以及它可能如何相关。