At this class i draw simple ground for Tic-Tae-Toe. It consists of intercepted lines and "X" in the center of the cell.
So when User touches the cell, then textColor
in it should be changed.
I use invalidate(rect)
to redraw concrete cell, but in this case every cell changes it's textColor
.
According to Romain Guy words, the canvas
with whole view Rect
comes
for drawing. The DisplayList
will find interceptions between drawing commands and your dirty Rect
, and only those commands will be drawn. But seems, that it doesn't work so way.
Partial invalidation in custom Android view with hardware acceleration
And also i found strange code change between 4.4 - 5.0 Android. So you can see, that mCurrentDirty
disappeared from code at all.
Android View.invalidate(Rect) different behavior between two devices
P.S for SA this logic works correctly, and only dirty Rect
is changed.
package com.eugeneshapovalov.fizmigclient
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import timber.log.Timber
class TicTacToeView : View, View.OnTouchListener {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
companion object {
const val CELL_SIZE_RATIO = 1 / 3f
const val LINE_SIZE = 2f
const val CELL_COUNT = 3
}
val linePaint = Paint()
val textPaint = Paint()
val dirtyCell = Rect()
var colorNumber: Int
init {
setOnTouchListener(this)
colorNumber = 0
linePaint.strokeWidth = resources.displayMetrics.density * LINE_SIZE
textPaint.textSize = 60f
}
private lateinit var cells: Array<Array<Rect>>
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
initCells()
}
private fun initCells() {
cells = Array(CELL_COUNT, { Array(CELL_COUNT, { Rect() }) })
val xCell = (width * CELL_SIZE_RATIO).toInt()
val yCell = (height * CELL_SIZE_RATIO).toInt()
for (i in 0 until CELL_COUNT) {
for (j in 0 until CELL_COUNT) {
cells[i][j].left = (x + j * xCell).toInt()
cells[i][j].top = (y + i * yCell).toInt()
cells[i][j].right = (x + (j + 1) * xCell).toInt()
cells[i][j].bottom = (y + (i + 1) * yCell).toInt()
}
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
drawLines(canvas)
drawText(canvas)
}
private fun drawLines(canvas: Canvas) {
// Vertical lines
canvas.drawLine(x + width * CELL_SIZE_RATIO, y, x + width * CELL_SIZE_RATIO, y + height, linePaint)
canvas.drawLine(x + width * 2 * CELL_SIZE_RATIO, y, x + width * 2 * CELL_SIZE_RATIO, y + height, linePaint)
// Horizontal lines
canvas.drawLine(x, y + height * CELL_SIZE_RATIO, x + width, y + height * CELL_SIZE_RATIO, linePaint)
canvas.drawLine(x, y + height * 2 * CELL_SIZE_RATIO, x + width, y + height * 2 * CELL_SIZE_RATIO, linePaint)
}
private fun drawText(canvas: Canvas) {
textPaint.color = when (colorNumber % 5) {
0 -> Color.BLACK
1 -> Color.BLUE
2 -> Color.RED
3 -> Color.GRAY
4 -> Color.YELLOW
else -> Color.GREEN
}
for (i in 0 until CELL_COUNT) {
for (j in 0 until CELL_COUNT) {
val rect = cells[i][j]
canvas.drawText("X", rect.exactCenterX(), rect.exactCenterY(), textPaint)
}
}
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_UP -> {
for (i in 0 until CELL_COUNT) {
for (j in 0 until CELL_COUNT) {
val rect = cells[i][j]
if (rect.contains(event.x.toInt(), event.y.toInt())) {
colorNumber += (j + 7)
Timber.d("Rect: ${rect.flattenToString()}")
invalidate(rect)
}
}
}
}
}
return true
}
}