2

2つのビューを持つ単純なアプリケーションがあります。1つはTableViewで、もう1つはListViewです。ここで行うのと同じように、GestureDetectorを使用して画面全体のスワイプを検出します。リストビューにいくつかの項目が表示されていれば、すべて正常に機能しますが、リストビューが画面全体に表示されると、ジェスチャ検出は機能しなくなります。画面をスワイプすると、リストアイテムの1つがハイライト表示されます。

ListViewがどういうわけかGestureListenerからタッチイベントを盗むので、これが起こっていると思います。これを防ぐ方法はありますか?

4

2 に答える 2

2

かなり正確な水平パスをトラバースすると、GestureDetectorがListItemsで正常に機能することがわかりました。ただし、少し外れると、リストがスクロールし、ジェスチャは完了しません。何が起こっているのかは次のとおりです。

  • GestureDetectorは、setOnTouchListener()を介してListItemsにインストールしたonTouchからMotionEventsを取得することから始めます。
  • その間、ListViewは、onInterceptTouchEvent()を介して子ビューに送信されたイベントをリッスンしています。
  • ListViewは、スクロールを開始したことを検出し、onInterceptTouchEvent()からtrueを返します。
  • それ以降、MotionEventsは元のターゲットではなくListViewに送信されます...ListViewはonTouchハンドラーでMotionEventsの受信を開始します。これは、最後のACTION_UPまで続きます。(ACTION_DOWNからすべてのACTION_MOVEからACTION_UPまでのMotionEventは単一のジェスチャと見なされ、シーケンスの最後のACTION_UPの後にすべてが再開されることに注意してください)
  • 元のターゲット(ListItem)はACTION_CANCEL MotionEventを取得し、ListItemのGestureDetectorがベイルアウトします。これは、GestureDetectorのコードをアプリに貼り付けて、ステップスルーすると発生することがわかります。

タッチが水平から少し外れたとしても、水平スワイプが続くかのようにアプリが動作する必要がありました。

解決策:これには、ViewGroup.requestDisallowInterceptTouchEvent(boolean disallowIntercept)が含まれ、親がモーションイベントをのぞき見するのを防ぎます。この方法では、onTouchListenerを実装してわずかなスワイプ(10ピクセル程度)を検出し、親がモーションイベントをインターセプトするのを停止します。その後、親はスクロールせず、ジェスチャ検出器は完了し続けます。

コードは次のとおりです。

private boolean mFlingInProgress = false;
private float mStartX = 0;
private final int FLING_TRIGGER_DISTANCE = 10;

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    float currentX = event.getRawX();

    switch (action) {
    case MotionEvent.ACTION_DOWN:
        mStartX = currentX;
        break;
    case MotionEvent.ACTION_MOVE:
        if (false == mFlingInProgress) {
            if (Math.abs(currentX - mStartX) > FLING_TRIGGER_DISTANCE) {
                // stop the parent intercepting motion events
                mLayout.getParent().requestDisallowInterceptTouchEvent(true);
                mFlingInProgress = true;
            }
        } 
        break;
    case MotionEvent.ACTION_UP:
        mFlingInProgress = false;
        break;
    }

    return mGestureDetector.onTouchEvent(event);
}
于 2012-11-05T22:52:37.273 に答える
1

カスタムリストビューを作成してから、この内部、つまりリストの各行にジェスチャ検出器を実装できます。試してみる価値があるかもしれません。

于 2010-12-15T13:23:09.040 に答える