как правильно добавить нескольких обьектов SurfaceView к ConstraintLayout по нажиманию пальцами
Моя программа сейчас рисует овал по нажатию пальца и водит его за пальцем.
Я хочу добавить мульти-нажатия, что бы не отпуская первого овала, нажав вторым пальцем добавить следующий.
Как сейчас работает мой код:
Здесь я создаю 20 овалов:
var ovalsViews = Array(20) { OvalsView(this) }
В функции MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN (здесь я ставлю палец на экран) я добавляю овалы из таблицы овалов к layout (ConstraintLayout):
layout.addView(ovalsViews[ID])
В функции MotionEvent.ACTION_MOVE (здесь я двигаю пальцем на экран) я меняю координаты каждого овала который держу пальцем:
ovalsViews[ID]._top = motionEvent.getY(ID)
ovalsViews[ID]._left = motionEvent.getX(ID)
И на конец, в функции MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP (здесь я отпускаю палец с экрана) я хочу удалить овал который держу пальцем:
layout.removeView(ovalsViews[ID])
Сейчас моя программа работает странно, когда я нажимаю один раз то все работает ок, но следующие нажатия не добавляют новый овалов. Так же когда я отпускаю первый палец то овал пропадает и что бы потом получить овал первый раз то тепер нужно будет надать два раза, потом три и так далее. Что я делаю не так?
Вот весь код:
package com.example.lab10
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.DisplayMetrics
import android.util.Log
import android.view.MotionEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.view.WindowManager
import androidx.constraintlayout.widget.ConstraintLayout
class TaskSevenNEW : AppCompatActivity() {
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_task_seven_new)
title = "Task#7 NEW"
val layout = findViewById<ConstraintLayout>(R.id.layout_7_NEW)
var ovalsViews = Array(20) { OvalsView(this) }
layout.setOnTouchListener(View.OnTouchListener { view, motionEvent ->
when (motionEvent.getActionMasked()) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
Log.d("touchInfo", "down")
val ID: Int = motionEvent.getPointerId(motionEvent.getActionIndex())
Log.d("touchInfo", "down ID: " + ID)
layout.addView(ovalsViews[ID])
}
MotionEvent.ACTION_MOVE -> {
Log.d("touchInfo", "move")
var idx = 0
while (idx < motionEvent.pointerCount) {
val ID: Int = motionEvent.getPointerId(idx) // pobranie unikalnego id dla każdego dotyku
idx++
Log.d("touchInfo", "move ID: " + ID)
ovalsViews[ID]._top = motionEvent.getY(ID)
ovalsViews[ID]._left = motionEvent.getX(ID)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
Log.d("touchInfo", "up")
val ID: Int = motionEvent.getPointerId(motionEvent.getActionIndex())
Log.d("touchInfo", "up ID: " + ID)
layout.removeView(ovalsViews[ID])
}
else -> Log.d("touchInfo", "unhandled")
}
return@OnTouchListener true
})
}
private class OvalsView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {
private val mSurfaceHolder: SurfaceHolder
private val mPainter = Paint()
private var mDrawingThread: Thread? = null
private val mDisplay = DisplayMetrics()
private var mDisplayWidth: Int
private var mDisplayHeight: Int
private var mRotation = 0f
private var running = true
var _top: Float = 0f
var _left: Float = 0f
init {
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.defaultDisplay.getMetrics(mDisplay)
mDisplayWidth = mDisplay.widthPixels
mDisplayHeight = mDisplay.heightPixels
mPainter.isAntiAlias = true
mPainter.color = Color.RED
mSurfaceHolder = holder
mSurfaceHolder.addCallback(this)
}
private fun animateOvals(): Boolean {
mRotation += 1
return true
}
private fun drawWheel(canvas: Canvas) {
canvas.drawColor(Color.WHITE)
// canvas.rotate(mRotation, mDisplayWidth / 2f, mDisplayHeight / 2f)
//drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)
// canvas.drawOval(mDisplayWidth/2f - 100f/2f - 100f, mDisplayHeight/2 + 100f/2f,
// mDisplayWidth/2f + 100f/2f + 100f, mDisplayHeight/2f - 100/2f, mPainter)
if (_top > 0f && _left > 0f)
canvas.drawOval(_left, _top, _left + 200f, _top + 350f, mPainter)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
mDisplayWidth = w
mDisplayHeight = h
super.onSizeChanged(w, h, oldw, oldh)
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
if (mDrawingThread != null) {
mDrawingThread!!.interrupt()
running = false
mDrawingThread!!.join()
Log.e("qqq", "Thread done")
}
}
override fun surfaceCreated(holder: SurfaceHolder) {
mDrawingThread = Thread(Runnable {
var frameStartTime = System.nanoTime();
var frameTime: Long = 0
var canvas: Canvas? = null
while (!Thread.currentThread().isInterrupted && animateOvals() && running) {
canvas = mSurfaceHolder.lockCanvas()
if (canvas != null) {
drawWheel(canvas)
mSurfaceHolder.unlockCanvasAndPost(canvas)
}
frameTime = (System.nanoTime() - frameStartTime) / 1000000
if (frameTime < MAX_FRAME_TIME) // faster than the max fps - limit the FPS
{
try {
Thread.sleep(MAX_FRAME_TIME - frameTime)
} catch (e: InterruptedException) {
// ignore
}
}
}
})
mDrawingThread!!.start()
}
}
}