ユーザーがビューAをタッチし、ビューBの上を下にドラッグした場合、タッチイベントを検出するにはどうすればよいですか。ビューBでタッチイベントを検出したいのですが。
ビューBにタッチリスナーを追加しましたが、ユーザーが最初にAにタッチしてBをドラッグした場合、イベントを受信しません。
ユーザーがビューAをタッチし、ビューBの上を下にドラッグした場合、タッチイベントを検出するにはどうすればよいですか。ビューBでタッチイベントを検出したいのですが。
ビューBにタッチリスナーを追加しましたが、ユーザーが最初にAにタッチしてBをドラッグした場合、イベントを受信しません。
次のコードを使用して、リクエストを達成できます。
ビューの境界をテストするメソッド(以下のコードで使用)
Rect outRect = new Rect();
int[] location = new int[2];
private boolean isViewInBounds(View view, int x, int y){
view.getDrawingRect(outRect);
view.getLocationOnScreen(location);
outRect.offset(location[0], location[1]);
return outRect.contains(x, y);
}
2人でテストTextView
final TextView viewA = (TextView) findViewById(R.id.textView);
final TextView viewB = (TextView) findViewById(R.id.textView2);
セットアップビューA
までアクティブな状態を維持するには、空OnClickListener
が必要ですOnTouchListener
ACTION_UP
viewA.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {}
});
viewA.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int)event.getRawX();
int y = (int)event.getRawY();
if(event.getAction() == MotionEvent.ACTION_UP){
if(isViewInBounds(viewB, x, y))
viewB.dispatchTouchEvent(event);
else if(isViewInBounds(viewA, x, y)){
Log.d(TAG, "onTouch ViewA");
//Here goes code to execute on onTouch ViewA
}
}
// Further touch is not handled
return false;
}
});
セットアップビューB
これは、viewB を押して viewA にドラッグする場合にのみ必要です。
viewB.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {}
});
viewB.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int)event.getRawX();
int y = (int)event.getRawY();
if(event.getAction() == MotionEvent.ACTION_UP){
if(isViewInBounds(viewA, x, y))
viewA.dispatchTouchEvent(event);
else if(isViewInBounds(viewB, x, y)){
Log.d(TAG, "onTouch ViewB");
//Here goes code to execute on onTouch ViewB
}
}
// Further touch is not handled
return false;
}
});
よろしく。
ViewGroup.dispatchTouchEvent(MotionEvent ev)
ビューAとビューBを含むViewGroupのオーバーライドメソッドが必要だと確信しています。元の実装では、コンテナが受信したときにターゲットビューを定義し、次のすべてのタッチイベントを受信またはMotionEvent.getAction() == MotionEvent.ACTION_DOWN
までターゲットビューにディスパッチします。MotionEvent.getAction() == MotionEvent.ACTION_UP
MotionEvent.ACTION_CANCEL
あなたの場合、ターゲットビューはAまたはコンテナ自体です(コンテナonInterceptTouchEvent(MotionEvent ev)
メソッドの実装に依存します)。したがって、このような動作をオーバーライドして、タッチイベントをターゲットビューだけでなく、タッチされた領域の下にあるすべてのビュー(たとえば、ビューB)にもディスパッチする必要があります。
興味のある方は、コードサンプルを共有していただければ、さらにサポートさせていただきます。
View
Aで、次のようにオーバーライドonTouchEvent
します。
@Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getRawX();
float y = event.getRawY();
if ( (B.getLeft() <= x <= B.getRight()) &&
(B.getTop() <= y <= B.getBottom())
)
{
Log.i("A", "Motion Event is currently above B");
B.dispatchTouchEvent(event);
}
return true;
}
View
Bで、同じメソッドをオーバーライドし、必ず false を返すようにします。
@Override
public boolean onTouchEvent(MotionEvent event)
{
//TODO handle touch event
return false;//this will allow A to continue using the event
}
ビュー A の onTouchEvent から true を返す場合、イベントは伝播されません。この特定のケースでは、A が B よりも下にある場合、ビュー A の onTouch から false が返されます。
また、コードを投稿していただけると助かります。
ドラッグ アンド ドロップ フレームワークを使用してみてください。
ビュー B を超えたら、それをonTouch
手動で呼び出します。
if (viewBRect.contains(x, y)) {
viewBsonTouch(view, motionEvent);
}