java - 如何使SurfaceView中的矩形对象可点击(setOnItemClickListener)

标签 java android surfaceview

我正在制作某种益智游戏,其中有 block ,用户必须单击它来移动 block ,并且我需要在每个单独的 block (矩形对象)上设置OnItemClickListener,因为每个 block 在以下情况下会有不同的行为根据其位置单击。现在我已经成功绘制了 block ,但我无法向每个不同的 block 添加项目单击监听器。

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

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

最佳答案

您无法向绘制的对象添加监听器。听众有不同的观点。

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

@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

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

关于java - 如何使SurfaceView中的矩形对象可点击(setOnItemClickListener),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32570014/

相关文章:

java - 如何从我的消息界面生成区域设置属性文件?

java - java语法中具有多个类型参数列表的构造函数

java - 如何从 ResultSet java sql 包中获取所有剩余的行

android - 如何从 ViewFinder 自定义 zxing 条码扫描器的捕获屏幕边框

java - 如何将调用 Request.callback onCompleted() 方法时从 Facebook 返回的数据传递到我在 Android 中的 fragment ?

android - 如何从表面 View 创建和保存屏幕截图?

java - 方法中的 <init> 方法调用错误?

android - 这个语音识别错误在我的 flutter 应用程序中意味着什么?

android - 从自定义 SurfaceView 获取位图

android - 如何使用 Android SurfaceView 实现每秒 30 帧?