Home > Back-end >  Trouble getting correct correct coordinates in translated Rect
Trouble getting correct correct coordinates in translated Rect

Time:10-03

Sorry if this is a noobish question, I am new to canvas/rect.

I have the following view which displays a grid of pixels using Bitmap of specific width/height:

class DrawingView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private lateinit var drawingViewBitmap: Bitmap
    private lateinit var boundingRect: Rect

    private var scaleWidth = 0f
    private var scaleHeight = 0f

    private var bitmapWidth = 15
    private var bitmapHeight = 15

    private val rectPaint = Paint().apply {
        style = Paint.Style.FILL
        color = Color.WHITE
        setShadowLayer(10f,0f, 0f, Color.argb(100, 0, 0, 0))
    }

    private fun setScaleWH() {
        scaleWidth = boundingRect.right.toFloat() / drawingViewBitmap.width.toFloat()
        scaleHeight = boundingRect.bottom.toFloat() / drawingViewBitmap.height.toFloat()
    }

    private fun setBoundingRect() {
        val ratio = if (bitmapWidth > bitmapHeight) {
            bitmapHeight.toDouble() / bitmapWidth.toDouble()
        } else {
            bitmapWidth.toDouble() / bitmapHeight.toDouble()
        }

        val rectW: Int = if (bitmapWidth > bitmapHeight) {
            width
        } else if (bitmapHeight > bitmapWidth) {
            (height * ratio).toInt()
        } else {
            width
        }

        val rectH: Int = if (bitmapWidth > bitmapHeight)  {
            (width * ratio).toInt()
        } else if (bitmapHeight > bitmapWidth) {
            height
        } else {
            width
        }

        val canvasCenter = Point(width / 2, height / 2)

        val left = canvasCenter.x - rectW / 2
        val top = canvasCenter.y - rectH / 2
        val right = canvasCenter.x   rectW / 2
        val bottom = canvasCenter.y   rectH / 2

        boundingRect = Rect(left, top, right, bottom)
    }

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

        if (::drawingViewBitmap.isInitialized) {
            drawingViewBitmap.recycle()
        }

        drawingViewBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)

        setBoundingRect()
        setScaleWH()
        requestLayout()
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        val coordinateX = (event.x / scaleWidth).toInt()
        val coordinateY = (event.y / scaleHeight).toInt()

        when (event.action) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
                if (coordinateX in 0 until drawingViewBitmap.width && coordinateY in 0 until drawingViewBitmap.height) {
                    drawingViewBitmap.setPixel(coordinateX, coordinateY, Color.BLACK)
                }
            }

            MotionEvent.ACTION_UP -> {
                drawingViewBitmap.drawTransparent()
            }
        }

        invalidate()

        return true
    }

    override fun onDraw(canvas: Canvas) {
        if (::drawingViewBitmap.isInitialized) {
            canvas.drawRect(boundingRect, rectPaint)
            canvas.drawBitmap(drawingViewBitmap, null, boundingRect, null)
        }
    }
}

I am having trouble getting the correct coordinates whenever the user taps on the screen. i always had trouble with doing these type of things

I think this is because the Rect is translated to the center I'm just unsure how to get the right coordinates of it.

For example, when the user taps on (3,3) I get the output (2,5) (wrong output).

Could someone let me know what I am exactly doing wrong? I do not know what I am doing wrong in my code. I tried to find a solution myself/look online but I have been unsuccessful as to how I would convert touch coordinates to rect coordinates.

CodePudding user response:

I fixed it by doing the following:

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
                if (event.x.toInt() in boundingRect.left..boundingRect.right && event.y.toInt() in boundingRect.top..boundingRect.bottom) {
                    val coordinateX = ((event.x - boundingRect.left) / scaleWidth).toInt()
                    val coordinateY = ((event.y - boundingRect.top) / scaleHeight).toInt()

                    drawingViewBitmap.setPixel(coordinateX, coordinateY, Color.BLACK)
                    invalidate()
                }
            }
        }

        return true
    }
    private fun setScaleWH() {
        scaleWidth = boundingRect.width() / drawingViewBitmap.width.toFloat()
        scaleHeight = boundingRect.height() / drawingViewBitmap.height.toFloat()
    }

  • Related