Detect touch event on a view when dragged over from other view
Asked Answered
B

7

23

How do I detect the touch event if the user touches on view A and drags to bottom over the view B. I want to detect the touch event in View B.

I added touch listener in view B but doesn't receive events if the user initially touched A and dragged over the B.

enter image description here

Bellis answered 19/10, 2012 at 18:20 Comment(1)
SEE THIS ALSODefilade
F
67

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.

Faviolafavonian answered 22/11, 2012 at 2:42 Comment(4)
how would the code look like in case of greater than 2 views?Annis
Cool nice one. Helped me.Blim
This code is not working for me. It shows only the last view i.e if i drag from ViewA to ViewB then it logs onTouch ViewB and if i drag from ViewB to ViewA then it logs onTouch ViewA. Please suggest. ThanksMarybellemarybeth
How can I just get x, y position on viewB of ACTION_MOVE triggered from viewA's touchlistener ?Dott
T
1

I'm sure that you need override ViewGroup.dispatchTouchEvent(MotionEvent ev) method in your ViewGroup that contains Views A and B. The original implementation defines the target view when the container receives MotionEvent.getAction() == MotionEvent.ACTION_DOWN and then dispatches all the following touch events to the target view until receives MotionEvent.getAction() == MotionEvent.ACTION_UP or MotionEvent.ACTION_CANCEL.

In your case the target view is A or the containter itself (depands on your container onInterceptTouchEvent(MotionEvent ev) method implementation). So you should override such behaviour and dispatch touch events not only to the target view, but also to all the views, that under the touched area (for example to view B).

If you are interested you can share code sample and I'll try to help you further.

Thumbtack answered 19/10, 2012 at 18:34 Comment(1)
I ALSO HAVE SAME PROBLEM AT THIS. can you give some demo code for help?Defilade
N
1

If you are returning true from the onTouchEvent of the view A then the event is not propagated. In this particular case when A is below B return false from onTouch of view A.

It would also help if you can post some code.

Newsy answered 16/11, 2012 at 4:53 Comment(0)
M
1

In View A, Override onTouchEvent as follows:

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

In View B, override the same method, making sure you return false:

@Override
public boolean onTouchEvent(MotionEvent event) 
{
    //TODO handle touch event
    return false;//this will allow A to continue using the event
}
Monaghan answered 19/11, 2012 at 18:27 Comment(1)
Let's let @Bellis test it out first. Or you could offer a constructive comment - such as why you believe it doesn't work and how you believe it should be adjusted.Monaghan
I
0

Try using the drag and drop framework.

Illaudable answered 19/10, 2012 at 18:32 Comment(1)
That is only avalible for 3.0 or laterGavotte
W
0

When you are over View B, call it's onTouch manually.

if (viewBRect.contains(x, y)) {
    viewBsonTouch(view, motionEvent);
}
Wretched answered 15/11, 2012 at 12:32 Comment(0)
A
0

how can I call the circle menu creation state when user lifts his finger from view B. Below is the sample code
circleMenu = findViewById(R.id.circle_menu);

    circleMenu.setMainMenu(Color.parseColor("#CDCDCD"), R.color.acik_yesil, 
    R.color.kirmizi)
                .addSubMenu(Color.parseColor("#258CFF"), R.drawable.add)
                .addSubMenu(Color.parseColor("#FF0000"), R.drawable.mul)
                .addSubMenu(Color.parseColor("#6d4c41"), R.drawable.sub)
                .addSubMenu(Color.parseColor("#FF077D8F"), R.drawable.div)
                .setOnMenuSelectedListener(new OnMenuSelectedListener() {
                    @Override
                    public void onMenuSelected(int index) {
                       
                        switch (index) {
                            case 0:
                                Toast.makeText(MainActivity.this, "add", 
      Toast.LENGTH_SHORT).show();
                                break;
                            case 1:
                                Toast.makeText(MainActivity.this, "mul", 
      Toast.LENGTH_SHORT).show();
                                break;
                case 2:
                                Toast.makeText(MainActivity.this, "sub", 
            Toast.LENGTH_SHORT).show();
                                break; 
                case 3:
                                Toast.makeText(MainActivity.this, "div", 
      Toast.LENGTH_SHORT).show();
                                break;
                        }
                    }
                });
Ava answered 2/5, 2021 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.