Cancel button press if user moves finger off button

血红的双手。 提交于 2020-01-23 12:25:55

问题


Here is my very standard button onTouchListener:

b.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
            b.setPressed(true);
        }
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
            b.setPressed(false);
            // Do the button action stuff here
        }
        return true;
    }
});

When the user presses down on the button I set the button to "pressed". When the user lifts the finger I set the button to "not pressed" and then do the stuff the button is supposed to do.

This is all great except for the case where the user presses the button and then, while continuing to keep the finger down, moves the finger outside of the button area. When the finger is lifted the ACTION_UP stuff runs anyway. I would like for this behavior to act as a "cancel" of the button press. So, as soon as the pressed finger moves outside the button area I'd like to b.setPressed(false); and then NOT do the button action stuff when the finger is raised.

I've tried using MotionEvent.ACTION_CANCEL and MotionEvent.ACTION_OUTSIDE (as suggested by How to detect when finger slides off the ImageButton?) but I must be missing something because they're not working.

From Detect when a user moves off of a button in Android it would appear that this can be done with event.getX() and event.getY(). If getX() is negative you're off the left and if getY() is negative you're off the top, but to figure out if you're off the right or bottom I'll have to figure out the size of the button and then... there has to be a simpler way. Is there?


回答1:


You had the right answer. Use getWidth() and getHeight() to get the width and height and check if x or y is greater.

ACTION_CANCEL doesn't work because CANCEL is generated when a parent view takes control of the touch events, like a ListView does when scrolling.

ACTION_OUTSIDE only happens in some unusual cases where you request it. It isn't going to be generated for just a normal MOVE or UP.




回答2:


Since no one posted any code, here is one. A Boolean is used to indicate when the respective actions should be performed.

The MotionEvent.ACTION_MOVE event is handled to check if the finger is moved out of the bounds. If yes, b.setPressed(false); is called and the boolean is used to indicate that MotionEvent.ACTION_UP shouldn't be fired the next time, ie to cancel the button click.

And in MotionEvent.ACTION_UP, call b.setPressed(false); only if our boolean doesn't indicate a skip (as mentioned above). And if it does, invert the boolean so that button action stuff would execute the next time.

private Boolean notNow = false;
private Rect rect;    // Variable rect to hold the bounds of the view

b.setOnTouchListener(new OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event){
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN){
            b.setPressed(true);
            rect = new Rect(v.Left, v.Top, v.Right, v.Bottom);
        }
        if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP){
            if (!notNow){
                b.setPressed(false);
            }
            else //button press canceled
                notNow = false;  
        }
        if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE){
            if(!notNow)
                if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){ 
                    // finger moved out of bounds
                    b.setPressed(false);
                    notNow = true; //cancel button press the next time
                }
        }

        return true;
});


来源:https://stackoverflow.com/questions/24710547/cancel-button-press-if-user-moves-finger-off-button

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!