Below is a code that allows you to draw something on the screen, and after a few seconds, as the user releases his finger, it is redrawn automatically.
It is necessary that when recompiling points were drawn with a certain interval (delay) relative to each other. How to implement it?
class MainActivity : AppCompatActivity() { internal lateinit var dv: DrawingView var points: ArrayList<IntermediatePoint>? = null private var mPaint: Paint? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) dv = DrawingView(this) setContentView(dv) mPaint = Paint() mPaint!!.isAntiAlias = true mPaint!!.isDither = true mPaint!!.color = Color.GREEN mPaint!!.style = Paint.Style.STROKE mPaint!!.strokeJoin = Paint.Join.ROUND mPaint!!.strokeCap = Paint.Cap.ROUND mPaint!!.strokeWidth = 12f points = ArrayList(); } inner class DrawingView(internal var context: Context) : View(context) { var width: Int? = 0 var height: Int? = 0 private var mBitmap: Bitmap? = null private var mCanvas: Canvas? = null private val mPath: Path private val mBitmapPaint: Paint private val circlePaint: Paint private val circlePath: Path private var mX: Float = 0.toFloat() private var mY: Float = 0.toFloat() private val TOUCH_TOLERANCE = 4f init { mPath = Path() mBitmapPaint = Paint(Paint.DITHER_FLAG) circlePaint = Paint() circlePath = Path() circlePaint.isAntiAlias = true circlePaint.color = Color.BLUE circlePaint.style = Paint.Style.STROKE circlePaint.strokeJoin = Paint.Join.MITER circlePaint.strokeWidth = 4f } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888) mCanvas = Canvas(mBitmap!!) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) canvas.drawBitmap(mBitmap!!, 0f, 0f, mBitmapPaint) canvas.drawPath(mPath, mPaint!!) canvas.drawPath(circlePath, circlePaint) } private fun touch_start(x: Float, y: Float) { mPath.reset() mPath.moveTo(x, y) mX = x mY = y } private fun touch_move(x: Float, y: Float) { val dx = Math.abs(x - mX) val dy = Math.abs(y - mY) if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2) mX = x mY = y circlePath.reset() Log.d("KAK","TAK"); circlePath.addCircle(mX, mY, 30f, Path.Direction.CW) } } private fun touch_up() { mPath.lineTo(mX, mY) circlePath.reset() // commit the path to our offscreen mCanvas!!.drawPath(mPath, mPaint!!) // kill this so we don't double draw mPath.reset() mCanvas?.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) // for (item in points!!){ // Log.d("TEST X: ", item.x.toString()) // Log.d("TEST Y: ", item.y.toString()) // Log.d("TEST TIME: ", item.time.toString()) // } } override fun onTouchEvent(event: MotionEvent): Boolean { val x = event.x val y = event.y val time = System.currentTimeMillis() Log.d("WTF", time.toString()) Log.d("KEK ", "xMain: = )$x yMain: = $y") // var point:IntermediatePoint = IntermediatePoint(time,x,y); // points?.add(point) when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d("KEK ", "xStart: = )$x yStart: = $y") var point: IntermediatePoint = IntermediatePoint(time, x, y); points?.add(point) touch_start(x, y) invalidate() } MotionEvent.ACTION_MOVE -> { Log.d("KEK ", "xMove: = )$x yMove: = $y") var point: IntermediatePoint = IntermediatePoint(time, x, y); points?.add(point) touch_move(x, y) invalidate() } MotionEvent.ACTION_UP -> { Log.d("KEK ", "xUp: = )$x yUp: = $y") var point: IntermediatePoint = IntermediatePoint(time, x, y); points?.add(point) touch_up() invalidate() Handler().postDelayed(Runnable { for (i in points!!.indices) { Log.d("KEK ", "xStartPost: = )${points!![i].x} yStartPost: = ${points!![i].y}") if (i == 0) { touch_start(points!![0].x, points!![0].y) invalidate(); } else if (i == points!!.size - 1) { touch_move(points!![i].x, points!![i].y) invalidate(); } else { touch_move(points!![i].x, points!![i].y) invalidate(); } } points?.clear() }, 5000) } } return true } } }