かなり正確な水平パスをトラバースすると、ListItemsでGestureDetectorが正常に動作することがわかりました。しかし、少し浮いた場合、リストがスクロールしてジェスチャーが完了しません。次のように何が起こっていることである。
- GestureDetectorは喜んであなたがsetOnTouchListener()を介してのListItemにインストールonTouchからMotionEventsを取ってオフに開始されます。
- ListViewはonInterceptTouchEvent()経由で子ビューに送信されたイベントをリッスンします
- リストビューは、スクロールを開始したことを検出し、onInterceptTouchEvent()からtrueを返します。
- その後、MotionEventsはListViewに送信され、元のターゲットには送信されません。リストビューはonTouchハンドラでMotionEventsの受信を開始します。これは最後のACTION_UPまで続きます。 (ACTION_DOWNからACTION_UPまでのMotionEventsは1つのジェスチャーとみなされ、シーケンス内の最後のACTION_UPの後にすべてが再び開始されます)
- 元のターゲット(ListItem)は、ListItem bailsのACTION_CANCEL MotionEventと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);
}
私はそれについて考え、何かクリーナーを探しています。 – Vlad