如何使 SurfaceView 内的矩形对象可点击(setOnItemClickListener)

How to make rect object inside SurfaceView clickable (setOnItemClickListener)

我正在制作某种益智游戏,其中有方块,用户必须点击它才能移动方块,我需要在每个单独的方块(矩形对象)上设置 setOnItemClickListener,因为每个方块都会起作用根据其位置单击时会有所不同。现在我已经设法绘制了块,但是我无法为每个不同的块添加项目点击监听器。

MainActivity.java

public class MainActivity extends Activity {

    PuzzleView puzzleView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Get a display object to access screen details
        Display display = getWindowManager().getDefaultDisplay();
        // Load the resolution into a Point object
        Point size = new Point();
        display.getSize(size);

        // Initialize gameView and set it as the view
        puzzleView = new PuzzleView(this, size.x, size.y);
        setContentView(puzzleView);
    }

    // This method executes when the player starts the game
    @Override
    protected void onResume() {
        super.onResume();

        // Tell the gameView resume method to execute
        puzzleView.resume();
    }
}

PuzzleView.java

public class PuzzleView extends SurfaceView implements Runnable {

    Context context;

    // This is our thread
    private Thread gameThread = null;

    // Our SurfaceHolder to lock the surface before we draw our graphics
    private SurfaceHolder ourHolder;

    // A boolean which we will set and unset
    // When the game is running or not
    private volatile boolean playing;

    // Game is paused at the start
    private boolean paused = true;

    // A canvas and a Paint object
    private Canvas canvas;
    private Paint paint;

    // Size of screen in pixels
    private int screenX;
    private int screenY;

    // Blocks of puzzle
    private Block[] blocks = new Block[10];
    private int numBlocks;

    // Position of block
    private int block_right;

    // When we initialize call on gameView
    // This constructor runs
    public PuzzleView(Context context, int x, int y) {
        // Ask SurfaceView class to set up our object
        super(context);

        // Make a globally available copy of the context so we can use it in another method
        this.context = context;

        // Initialize ourHolder and paint objects
        ourHolder = getHolder();
        paint = new Paint();

        screenX = x;
        screenY = y;

        block_right = 0;

        prepareLevel();

    }

    private void prepareLevel() {
        // Here we will intialize all game objects

        // Build the blocks
        numBlocks = 0;
        for(int column = 0; column < 2; column++) {
            for(int row = 0; row < 2; row++) {
                blocks[numBlocks] = new Block(row, column, screenX, screenY);
                numBlocks++;
            }
        }

    }

    @Override
    public void run() {
        while(playing) {
            // Update the frame
            if(!paused) {
                update();
            }

            // Draw the frame
            draw();
        }
    }

    private void update() {
        // Move the block
    }

    private void draw() {
        // Make sure our drawing surface is valid or we crash
        if(ourHolder.getSurface().isValid()) {
            // Lock the canvas ready to draw
            canvas = ourHolder.lockCanvas();

            // Draw the background color
            canvas.drawColor(Color.argb(255, 255, 255, 255));

            // Choose the brush color for drawing
            paint.setColor(Color.RED);

            // Draw the block
            for(int i = 0; i < numBlocks; i++) {
                canvas.drawRect(blocks[i].getRect(), paint);
            }

            //Change brush color for text
            paint.setColor(Color.BLACK);
            // Draw the score
            paint.setTextSize(20);
            canvas.drawText("Right: " + block_right, 10, screenY - 50, paint);

            // Draw everything to the screen
            ourHolder.unlockCanvasAndPost(canvas);
        }

    }

    // If MainActivity is started then start our thread
    public void resume() {
        playing = true;
        gameThread = new Thread(this);
        gameThread.start();
    }

}

Block.java

public class Block {

    private RectF rect;

    public Block(int row, int column, int screenX, int screenY) {

        int padding = 1;
        int width = 50;
        int height = 50;
        int outer_padding = (screenX - 104) / 2;

        rect = new RectF(column * width + padding + outer_padding,
                row * height + padding + 40,
                column * width + width - padding + outer_padding,
                row * height + height - padding + 40);
    }

    public RectF getRect() {
        return this.rect;
    }
}

现在如何为每个块对象创建点击事件侦听器? 非常欢迎所有建议和改进。 提前致谢。

您不能为绘制的对象添加监听器。听众是为了不同的观点。

如果您想自己绘制所有内容,您仍然可以确定是否在矩形内部发生了触摸事件:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      // Check if click is within bounds of your rect
      if (event.getX() >= mRectStartX && event.getX() <= mRectEndX && event.getY() >= mRectStartY && event.getY() <= mRectEndY) {
        // Clicked within your rect, register further clicks by consuming this click
        return true;
      }
    }

    return super.onTouchEvent(event);
}

检测到触摸后,您必须重新绘制矩形。

这比简单的点击侦听器复杂得多,但这就是你想要自己绘制的结果:P

P.S。您可以使用 GestureDetector 来简化此过程,但本质上它保持不变。