【问题标题】:Cancel button press if user moves finger off button如果用户将手指移开按钮,则取消按钮按下
【发布时间】:2014-09-02 20:03:18
【问题描述】:

这是我非常标准的 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;
    }
});

当用户按下按钮时,我将按钮设置为“按下”。当用户抬起手指时,我将按钮设置为“未按下”,然后执行按钮应该执行的操作。

这一切都很好,除了用户按下按钮然后在继续保持手指向下的同时将手指移到按钮区域之外的情况。当手指被抬起时,ACTION_UP 东西无论如何都会运行。我希望这种行为充当按钮按下的“取消”。因此,只要按下的手指移出按钮区域,我就想b.setPressed(false);,然后在手指抬起时不要执行按钮操作。

我尝试过使用MotionEvent.ACTION_CANCEL 和MotionEvent.ACTION_OUTSIDE(如How to detect when finger slides off the ImageButton? 所建议的那样),但我一定错过了一些东西,因为它们不起作用。

从Detect when a user moves off of a button in Android 看来,这可以通过event.getX() 和event.getY() 完成。如果 getX() 为负数,则您不在左侧,如果 getY() 为负,您不在顶部,但要弄清楚您是在右侧还是底部,我必须弄清楚按钮,然后......必须有一个更简单的方法。有吗?

【问题讨论】:

    标签: android button ontouchlistener


    【解决方案1】:

    你有正确的答案。使用getWidth() 和getHeight() 获取宽度和高度并检查x 或y 是否更大。

    ACTION_CANCEL 不起作用,因为 CANCEL 是在父视图控制触摸事件时生成的,就像滚动时 ListView 所做的那样。

    ACTION_OUTSIDE 仅在您请求它的某些特殊情况下发生。它不会为普通的MOVE 或UP 生成。

    【讨论】:

    • 谢谢。 getX() 和 get(y) 不会是大量的工作,但我很惊讶没有“内置”的方法来做到这一点,因为它似乎是一个如此明显的按钮功能。感谢投反对票的人。
    • stackoverflow.com/questions/14414873/… 似乎描述了类似的情况,并且 ACTION_CANCEL 显然有效。也许我不明白那里发生了什么。
    • ACTION_CANCEL 在父视图(如滚动视图或列表视图)获得触摸事件的所有权时生成 - 例如当滚动视图认为您正在滚动时。除非您处于类似的视图中,否则您不会在此处看到取消操作。
    • 好的,我不得不承认没有一种优雅的方法可以做到这一点。对我来说仍然很奇怪,但我想就是这样。
    【解决方案2】:

    由于没有人发布任何代码,这里是一个。布尔值用于指示何时应执行相应的操作。

    处理MotionEvent.ACTION_MOVE 事件以检查手指是否移出边界。如果是,则调用b.setPressed(false);,并使用布尔值指示下次不应触发MotionEvent.ACTION_UP,即取消按钮单击。

    并且在MotionEvent.ACTION_UP 中,仅当我们的布尔值不表示跳过时才调用b.setPressed(false);(如上所述)。如果是,则反转布尔值,以便下次执行按钮操作。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-14
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多