Android: Detect if user touches and drags out of button region?

前端 未结 9 1984
孤城傲影
孤城傲影 2020-12-04 16:33

In Android, how can we detect if a user touches on button and drags out of region of this button?

相关标签:
9条回答
  • 2020-12-04 17:06
    view.setClickable(true);
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (!v.isPressed()) {
                Log.e("onTouch", "Moved outside view!");
            }
            return false;
        }
    });
    

    view.isPressed uses view.pointInView and includes some touch slop. If you don't want slop, just copy the logic from the internal view.pointInView (which is public, but hidden so it's not a part of the official API and could disappear at any time).

    view.setClickable(true);
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                v.setTag(true);
            } else {
                boolean pointInView = event.getX() >= 0 && event.getY() >= 0
                        && event.getX() < (getRight() - getLeft())
                        && event.getY() < (getBottom() - getTop());
                boolean eventInView = ((boolean) v.getTag()) && pointInView;
                Log.e("onTouch", String.format("Dragging currently in view? %b", pointInView));
                Log.e("onTouch", String.format("Dragging always in view? %b", eventInView));
                v.setTag(eventInView);
            }
            return false;
        }
    });
    
    0 讨论(0)
  • 2020-12-04 17:07

    I added some logging in my OnTouch and found out that MotionEvent.ACTION_CANCEL was being hit. That's good enough for me...

    0 讨论(0)
  • 2020-12-04 17:10

    The top 2 answers are fine except when the view is inside a scrollview: when scrolling takes place because you move your finger, it is still registered as a touch event but not as a MotionEvent.ACTION_MOVE event. So to improve the answer (which is only needed if your view is inside a scroll element):

    private Rect rect;    // Variable rect to hold the bounds of the view
    
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            // Construct a rect of the view's bounds
            rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
    
        } else if(rect != null && !rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
            // User moved outside bounds
        }
        return false;
    }
    

    I tested this on Android 4.3 and Android 4.4

    I haven't noticed any differences between Moritz's answer and to top 2 but this also applies for his answer:

    private Rect rect;    // Variable rect to hold the bounds of the view
    
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            // Construct a rect of the view's bounds
            rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
    
        } else if (rect != null){
            v.getHitRect(rect);
            if(rect.contains(
                    Math.round(v.getX() + event.getX()),
                    Math.round(v.getY() + event.getY()))) {
                // inside
            } else {
                // outside
            }
        }
        return false;
    }
    
    0 讨论(0)
提交回复
热议问题