Detect Touch Event on a View When Dragged Over from Other View

How to detect view has been touched when dragged over from another view

I couldn't find a way to do this through the actual custom views and had to go one layer back.

The position of the views are documented on the FrameLayout that contains each view.

In the FrameLayout, I ended up overwriting onTouchEvent.

I ended up having to do something similar to this:

@Override
public boolean onTouchEvent(MotionEvent event) {

float xCoord = event.getX();
float yCoord = event.getY();

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Using X and Y coordinates, find out if touch event is on top of a view.
// Mark the view as touched
return true;
case MotionEvent.ACTION_UP:
// Action required once touch released.
return true;
default:
// When dragging, the default case will be called.
// Using X and Y coordinates, figure out if finger goes over a view.
// If you don't want same behaviour when going back to previous view,
// then mark it so you can ignore it if user goes back to previous view.

}
}

Once case MotionEvent.ACTION_UP gets called, you can use the fact that the views were marked to know which ones were touched. You can also get the order if required by putting the views in an array when marking them.

Detect touch event on a view when dragged over from other view

You can use the code bellow to achive your request:

Method to test view bounds (used in code beloow)

    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);
}

Testing with two TextView

    final TextView viewA = (TextView)  findViewById(R.id.textView);
final TextView viewB = (TextView) findViewById(R.id.textView2);

Setup viewA

The empty OnClickListener is required to keep OnTouchListener active until 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;
}
});

Setup viewB

This is only required if you also want to press on viewB and drag to 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;
}
});

Regards.

How to implement detection of a View being dragged over another view?

The animated translation is unnecessary since the touch events should move the TextView smoothly about. Just assign new X,Y coordinates to the TextView, like this:

view.setX(view.getX() + deltaX);
view.setY(view.getY() + deltaY);

Determine which view is currently being Touched while user Moves finger

Found my answer here:

Android : Get view only on which touch was released

Looks like you have to loop through the child views and do hit detection manually to find which view the touch is currently over.

Did this by overriding dispatchTouchEvent on the parent LinearLayout:

LinearLayout parent = new LinearLayout(this.getActivity()){
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = Math.round(ev.getX());
int y = Math.round(ev.getY());
for (int i=0; i<getChildCount(); i++){
LinearLayout child = (LinearLayout)row.getChildAt(i);
if(x > child.getLeft() && x < child.getRight() && y > child.getTop() && y < child.getBottom()){
//touch is within this child
if(ev.getAction() == MotionEvent.ACTION_UP){
//touch has ended
}
}
}
return true;
}
}


Related Topics



Leave a reply



Submit