Home > Software design >  Android Canvas Rect.contains(x, y) only firing for top left Rect
Android Canvas Rect.contains(x, y) only firing for top left Rect

Time:12-08

I have a grid of pixels (Rect) inside of a Canvas which looks like the following:

enter image description here

Code:

class MyCanvasView(context: Context) : View(context) {
    private lateinit var extraCanvas: Canvas
    private lateinit var extraBitmap: Bitmap

    private val spanCount = 10.0

    private val rectangles = mutableListOf<RectF>()

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        if (::extraBitmap.isInitialized) extraBitmap.recycle()

        extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        extraCanvas = Canvas(extraBitmap)

        val scale = (w / spanCount)

        for (i in 0..spanCount.toInt()) {
            for (i_2 in 0..spanCount.toInt()) {
                val rect = RectF(
                    ((i * scale).toFloat()),
                    ((i_2 * scale).toFloat()),
                    scale.toFloat(),
                    scale.toFloat()
                )
                Log.d("MY_LOG", "LEFT: ${((i * scale).toFloat())} TOP: ${((i_2 * scale).toFloat())} ")

                rectangles.add(rect)
                extraCanvas.drawRect(
                    rect,
                    Paint().apply {
                        style = Paint.Style.FILL
                        color = Color.WHITE
                    })
            }
        }

        for (i in 0..spanCount.toInt()) {
            for (i_2 in 0..spanCount.toInt()) {
                extraCanvas.drawRect(
                    (i * scale).toFloat(),
                    (i_2 * scale).toFloat(),
                    scale.toFloat(),
                    scale.toFloat(),
                    Paint().apply {
                        color = Color.GRAY
                        style = Paint.Style.STROKE
                    })
            }
        }

    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        val x = event.rawX
        val y = event.rawY

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                for (rect in rectangles) {
                    if (rect.contains(x, y)) {
                        Toast.makeText(context, "Touched", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }

        return true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawBitmap(extraBitmap, 0f, 0f, null)
    }
}

For some reason, the dispatchTouchEvent is only firing for the top left rectangle here:

enter image description here

... but not for the other ones.

If anyone knows why this is the case please let me know, I'm new to all of this Canvas stuff so I understand there's probably something wrong in my code.

CodePudding user response:

I believe because your bottom and right coordinates are always the same:

val left = (i * scale).toFloat()
val top = (i_2 * scale).toFloat()
val rect = RectF(
    left, 
    top,
    left   scale.toFloat(),
    top   scale.toFloat()
    )
  • Related