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