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

}

    1 answer 1

    1. While the animation lasts (the state changes), you need to know how much time has passed. To do this, you need to create a field in which uptimeMillis will be written at the beginning of the animation.
    2. In onDraw, you need to draw points, based on the current state, which is calculated from the difference between the current uptimeMillis and the saved one.
    3. Until the animation is finished, you must call invalidate from onDraw. Then this view will be drawn in the next frame.

    In general - something like that.

    PS Nullabiliтиi is not done in order to do everything nullabelny and place exclamation marks. Mixing Hungarian notation with normal code looks scary.