スワイプを検出したいSliderViewと呼ぶトップレベルのViewGroupがあります。これはほとんど機能していますが、奇妙な失敗が 1 つあります。
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 を受け取る必要があることを理解しています。私のテストの 1 つで、最上位の子は ですが、次のケースではそうではないようです。
最上位の子が ScrollView の場合、onInterceptTouchEvent は ACTION_MOVE を取得し、私のコードは私が望むことを行います。最上位の子が LinearLayout である別のケースでは、時々失敗します。常に ACTION_DOWN を取得しますが、ユーザーが LinearLayout 内のウィジェットに触れた場合にのみ ACTION_MOVE を取得します。空白の領域に触れると、ACTION_DOWN のみが通過します。
失敗した場合のタッチが SliderView の外部で発生しているかのように動作することに注意してください。しかし、その場合、なぜ ACTION_DOWN イベントが発生するのでしょうか?
2 番目の注意: ScrollView のソース コードを見ると、"inChild" をチェックしていることがわかります。それが何のためにあり、どのように関連するのかはわかりません。