【问题标题】:Android - onTouchEvent only working first timeAndroid - onTouchEvent 只在第一次工作
【发布时间】:2012-07-25 09:30:24
【问题描述】:

我有一个使用 OnTouch 的画布绘图,但由于某种原因,我无法使其正常工作。它第一次工作(第一次触摸运动)。但是,当用户移开手指时,OnTouch 不再运行,从而阻止用户移动字符项。

经过大量研究和各种不同的选择,我根本无法让它工作,并且在这样做时注意到第一次调用 ACTION_DOWN 然后调用 ACTION_UP。

您可以在下面找到我的两段代码,第一段是实际的 onTouchEvent。第二块代码用于处理我绘制的画布(基于迷宫(5 x 5))中的用户权限。

另一个需要考虑的问题是画布被重绘(无效),每次移动用户位置(这是一个正方形)

@Override
public boolean onTouchEvent(MotionEvent event) 
{
        float touchX = event.getX();
        float touchY = event.getY();
        int currentX = maze.getCurrentX();
        int currentY = maze.getCurrentY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) 
        {
            case MotionEvent.ACTION_DOWN:
                if(Math.floor(touchX/totalCellWidth) == currentX && Math.floor(touchY/totalCellHeight) == currentY) 
                {
                    dragging = true;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                dragging = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if(dragging) 
                {
                    int cellX = (int)Math.floor(touchX/totalCellWidth);
                    int cellY = (int)Math.floor(touchY/totalCellHeight);

                    if((cellX != currentX && cellY == currentY) || (cellY != currentY && cellX == currentX)) 
                    {
                        boolean moved = false;
                        switch(cellX-currentX) 
                        {
                            case 1:
                                moved = maze.move(Maze.RIGHT);
                                break;
                            case -1:
                                moved = maze.move(Maze.LEFT);
                        }
                        switch(cellY-currentY) 
                        {
                            case 1:
                                moved = maze.move(Maze.DOWN);
                                break;
                            case -1:
                                moved = maze.move(Maze.UP);
                        }

                        if(moved) 
                        {
                            invalidate();
                            if(maze.isGameComplete()) 
                            {
                                showFinishDialog();
                            }
                        }
                    }
                    break;
                }
    }
    return true;
}

迷宫位置处理代码:

public boolean move(int direction) 
{
    boolean moved = false;
    if(direction == UP) 
    {
        if(currentY != 0 && !horizontalLines[currentY-1][currentX]) 
        {
            currentY--;
            moved = true;
        }
    }
    if(direction == DOWN) 
    {
        if(currentY != verticalLines[0].length-1 && !horizontalLines[currentY][currentX]) 
        {
            currentY++;
            moved = true;
        }
    }
    if(direction == RIGHT) 
    {
        if(currentX != horizontalLines[0].length-1 && !verticalLines[currentY][currentX]) 
        {
            currentX++;
            moved = true;
        }
    }
    if(direction == LEFT) 
    {
        if(currentX != 0 && !verticalLines[currentY][currentX-1]) 
        {
            currentX--;
            moved = true;
        }
    }
    if(moved) 
    {
        if(currentX == finalX && currentY == finalY) 
        {
            gameComplete = true;
        }
    }
    return moved;
}

【问题讨论】:

  • 从开关盒中移除 MotionEvent.ACTION_MASK
  • @AkashG,试过了,但我的其他想法没有用?
  • 你的意思是当用户第一次执行 ACTION_DOWN+MOVE+UP 时它可以,但下次它不起作用?第二次进入MOVE和拖动是否等于true?
  • @Dayerman,这正是我的意思,它似乎没有被第二次触发
  • 第二次进入MOVE和拖动是否相等? (尝试调试或记录)

标签: java android touch-event


【解决方案1】:

试图改变最终返回为真而不是假 像这样:

@Override
public boolean onTouchEvent(MotionEvent event) 
{
float touchX = event.getX();
float touchY = event.getY();
int currentX = maze.getCurrentX();
int currentY = maze.getCurrentY();
switch (event.getAction() & MotionEvent.ACTION_MASK) 
{
    case MotionEvent.ACTION_DOWN:
    {
        if(Math.floor(touchX/totalCellWidth) == currentX &&Math.floor(touchY/totalCellHeight) == currentY) 
        {
            dragging = true;
            return true;
        }
    }
    case MotionEvent.ACTION_UP:
        dragging = false;
        return true;
    case MotionEvent.ACTION_MOVE:
        if(dragging) 
        {
            int cellX = (int)Math.floor(touchX/totalCellWidth);
            int cellY = (int)Math.floor(touchY/totalCellHeight);

            if((cellX != currentX && cellY == currentY) || (cellY != currentY && cellX == currentX)) 
            {
                //either X or Y changed
                boolean moved = false;
                //check horizontal ball movement
                switch(cellX-currentX) 
                {
                case 1:
                    moved = maze.move(Maze.RIGHT);
                    break;
                case -1:
                    moved = maze.move(Maze.LEFT);
                }
                //check vertical ball movement
                switch(cellY-currentY) 
                {
                case 1:
                    moved = maze.move(Maze.DOWN);
                    break;
                case -1:
                    moved = maze.move(Maze.UP);
                }

                if(moved) 
                {
                    invalidate();
                    if(maze.isGameComplete()) 
                    {
                        showFinishDialog();
                    }
                }
            }
            return true;
        }
  }
    return True;  // Here 
 }

【讨论】:

  • 请查看我修改后的 onTouch 代码,尽管我已将 end return 改回 false(但这仍然无法正常工作)。
【解决方案2】:

看起来像面具和你在开关上应用的事件有问题。看看这个issue

【讨论】:

  • 请查看我修改后的 onTouch 代码(这仍然无法正常工作)。
【解决方案3】:

这里有一个很好的触摸示例,不确定是否有用?

 public boolean onTouch(View v, MotionEvent event) {
   layoutParams = (RelativeLayout.LayoutParams) ima1.getLayoutParams();

     switch(event.getAction())                   
        {
          case MotionEvent.ACTION_DOWN:                          
                break;     

          case MotionEvent.ACTION_MOVE:
                int x_cord = (int) event.getRawX();
                int y_cord = (int) event.getRawY();

          System.out.println("value of x" +x_cord);
          System.out.println("value of y" +y_cord);           

                if (x_cord > windowwidth) {
                    x_cord = windowwidth;
                   }
                if (y_cord > windowheight) {
                    y_cord = windowheight;
                   }
         layoutParams.leftMargin = x_cord-25;
         layoutParams.topMargin = y_cord-25;
         //   layoutParams.rightMargin = x_cord-25;
         //   layoutParams.bottomMargin = y_cord-25;
         ima1.setLayoutParams(layoutParams);
                 break;
           default: break;
          }  
           return true;
        }
     });

     ima2 = (ImageView)findViewById(R.id.imageview2);
     ima2.setOnTouchListener(new View.OnTouchListener() {         

 public boolean onTouch(View v, MotionEvent event) {
     layoutParams = (RelativeLayout.LayoutParams) ima2.getLayoutParams();
          switch(event.getActionMasked())
             {
               case MotionEvent.ACTION_DOWN:
                   break;
               case MotionEvent.ACTION_MOVE:
                   int x_cord = (int) event.getRawX();
                   int y_cord = (int) event.getRawY();

                   System.out.println("value of x1" +x_cord);
               System.out.println("value of y1" +y_cord);                            

                    if (x_cord > windowwidth) {
                        x_cord = windowwidth;
                    }
                    if (y_cord > windowheight) {
                        y_cord = windowheight;
                    }
                    layoutParams.leftMargin = x_cord - 25;
                    layoutParams.topMargin = y_cord - 75;
                    ima2.setLayoutParams(layoutParams);
                    break;
                default: break;
            }
            return true;
        }
    });
   }     
 }

这是示例Android Drag and drop images on the Screen?

【讨论】:

  • 请查看我修改后的 onTouch 代码(这仍然无法正常工作)。
【解决方案4】:

我非常确定您的Touch 每次都被调用,我怀疑可能是您的案例不符合要求的原因。

要交叉检查,只需打印日志

@Override
public boolean onTouchEvent(MotionEvent event) 
{
   System.out.println("Touch working");
   return false;
}

【讨论】:

  • 是的,似乎每次我移动或触摸屏幕时都会调用它,例如如果我将我的用户向下移动 3 个空格,它会被调用 3 次,我该如何修复上面的代码以使其正常工作?谢谢
  • 请查看我修改后的 onTouch 代码(这仍然无法正常工作)。
【解决方案5】:

主要问题是您在每个案例的末尾都缺少一个 break 语句。 您遇到其他情况并在第二个 ACTION_DOWN 时返回 false。这意味着 ACTION_UP 和 MOVE 不会被调用。

要解决这个问题: - 在每个 case 的末尾添加一个 break 语句 - 总是从 ACTION_DOWN 返回 true

【讨论】:

  • 请查看我修改后的 onTouch 代码(这仍然无法正常工作)。
  • 尝试始终从 ACTION_DOWN 返回 true。如果您返回 false,您将永远不会收到 move 或 up 的调用。您需要对此进行调试:在代码中添加日志消息,然后查看您到达的位置和未到达的位置。
【解决方案6】:

不返回真,而是假。

if(Math.floor(touchX/totalCellWidth) == currentX && Math.floor(touchY/totalCellHeight) == currentY) 
{
    dragging = true;
    return false;
}

【讨论】:

  • 在此处返回 false 将完全破坏代码,并且第一次触摸不再起作用。还有其他想法吗?谢谢
【解决方案7】:

return=true; 放在 switch 案例的最后一条语句中,而不是 false 。因为如果你使用 false ,它只会调用一次,然后没有其他视图可以获取该特定视图的触摸事件..所以使用 true 而不是 false ..

理论
在 onTouchEvent() 中返回 true 会告诉 Android 系统您已经处理了触摸事件,不需要进一步处理。如果您返回 false,Android 系统将成为 onTouch 事件的处理程序,并将覆盖您的代码,处理超过 ACTION_DOWN 的任何事件(这是您触摸屏幕时的第一个事件)。

我也有同样的问题,现在解决了。我想它可以帮助你..

【讨论】:

  • 我现在在 switch 语句的末尾返回 true,但是仍然遇到同样的问题。请在我的问题中查看我修改后的 onTouch 代码。谢谢
【解决方案8】:

我认为有问题的部分是这个

 event.getAction() & MotionEvent.ACTION_MASK

不过再看一遍,好像还可以……试试把这个换成

 event.getMaskedAction()

并将其保留在开关中。

或者您可能需要使用 ACTION_POINTER_UP 而不是 ACTION_UP。

你能改一下这段代码吗?

case MotionEvent.ACTION_MOVE:
    Log.d(LOGTAG, "ACTION_MOVE block, dragging = "+dragging);
    if(dragging) 
    {
        Log.d(LOGTAG, "Dragging fired with event: "+event.toString());
        int cellX = (int)Math.floor(touchX/totalCellWidth);
        int cellY = (int)Math.floor(touchY/totalCellHeight);
        // ...

请发布输出。

编辑:另外,请记住,仅当您想完全使用事件时,您才想从 onlistener 返回 true;如果您想进一步传播它,请返回 false。所以我想只有其中一个返回需要为真,并让其他人传下来并由他们各自视图的 ontouch 处理程序处理......

【讨论】:

  • 嗨,我已经按照上面提到的相同方式修改了我的代码,但是它仍然无法正常工作。我在pastebin.com/mbn8mZ8g 处添加了我的新 onTouch 代码和错误日志。我还在日志中添加了我的 currentX 和 Y。最后,需要注意的是我的 onTouch 涉及绘制迷宫,基本上迷宫是 100x100 但只显示 5x5 因此当用户移动时,当前的 X&Y 会改变,因为他们在迷宫中的位置(这可能会影响 onTouch )。如果我们能在接下来的 4 小时内把它整理好,那么我可以理所当然地奖励你。谢谢
猜你喜欢
  • 2017-02-08
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
相关资源
最近更新 更多