そのレイアウトからのタッチを防ぐには、いくつかのオプションがあります。
1) 常に true を返す OnTouchListener を設定します。
2) dispatchTouchEvent(MotionEvent イベント) をオーバーライドして、常に true を返すようにします。
UPD:オーケー、通常は OnTouchListener を設定する必要があります。これは、他のビューが呼び出されないようにするために前に述べたように、常に true を返しますonTouch
が、ScrollView ではまったく別の話です。
まず、どのように機能するかを説明dispatchTouchEvent
します。ルートビューから子ビューへのイベントのディスパッチを開始するため、親が子dispatchTouchEvent
の前に呼び出されることを意味します。 dispatchTouchEvent
次に、ViewGroup.dispatchTouchEvent()
コードの一部があります
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
これは、このタッチ イベントをインターセプトする必要があるかどうかを決定します。つまり、intercepted
フラグが true の場合、このビューは後続のすべてのイベントをインターセプトします。また、ScrollView
onInterceptTouchEvent
垂直スクロールを実行している場合にアクションをインターセプトするために実装されています。
したがって、私の最初のアイデアはFLAG_DISALLOW_INTERCEPT
、カスタム ビューの親に設定して、イベントをインターセプトするこの機会を禁止することでしたが、次のコード行のためにこのアイデアは失敗しますViewGroup
。
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Throw away all previous state when starting a new touch gesture.
// The framework may have dropped the up or cancel event for the previous gesture
// due to an app switch, ANR, or some other state change.
cancelAndClearTouchTargets(ev);
resetTouchState();
}
つまり、MotionEvent.ACTION_DOWN
すべての状態がクリアされた後 (およびFLAG_DISALLOW_INTERCEPT
同様にクリアされます) ということです。
したがって、最終的な解決策は非常に簡単です
public class PreventingTouchEventView extends View {
public PreventingTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.RED);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (getParent() != null && event.getAction() == MotionEvent.ACTION_DOWN) {
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(event);
}
}
これはFLAG_DISALLOW_INTERCEPT
first の直後にMotionEvent.ACTION_DOWN
発生し、親による将来のアクションのさらなるインターセプトを禁止します。
ただし、親のビューがこのイベントでクレイジーなことを行ってインターセプトしている場合は、親のビューが の前に呼び出されるMotionEvent.ACTION_DOWN
ため、それについて何もできないことに注意してください。dispatchTouchEvent
dispatchTouchEvent