2

我有一个使用 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;
}
4

8 回答 8

1

尝试将最终返回更改为 True 而不是 False 像这样:

@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 
 }
于 2012-11-23T11:38:32.947 回答
0

不返回真,而是假。

if(Math.floor(touchX/totalCellWidth) == currentX && Math.floor(touchY/totalCellHeight) == currentY) 
{
    dragging = true;
    return false;
}
于 2012-11-26T06:08:37.003 回答
0

I thought the offending part is this one

 event.getAction() & MotionEvent.ACTION_MASK

But looking at it again, it seems ok... Try replacing this with

 event.getMaskedAction()

and keep that in the switch.

Or maybe you need to use ACTION_POINTER_UP instead of ACTION_UP.

Can you change this bit of code please?

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);
        // ...

and post the output please.

EDIT: also, remember that you want to return true from a onlistener ONLY when you want to fully consume the event; return false if you want to propagate it further. So i guess only one of those returns need to be true and let others pass down and be handled by their respective views' ontouch handlers...

于 2012-11-26T18:23:02.937 回答
0

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

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

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

于 2012-11-26T10:27:09.040 回答
0

here is good example of on touch may be it is usefull not sure?

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

this is example Android Drag and drop images on the Screen?

于 2012-11-20T05:17:12.983 回答
0

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

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

@Override
public boolean onTouchEvent(MotionEvent event) 
{
   System.out.println("Touch working");
   return false;
}
于 2012-11-23T04:11:13.613 回答
0

似乎是 Mask 和您在交换机上应用的事件有问题。看看这个问题

于 2012-07-25T12:25:19.970 回答
0

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

要解决这个问题: - 在每个案例的末尾添加一个 break 语句 - 始终从 ACTION_DOWN 返回 true

于 2012-11-24T08:26:45.353 回答