Prevent accidental draw before multitouch

If move action occurred before multitouch, cancel drawing it if it was touch slop – "distance in pixels a touch can wander before we think the user is scrolling".
This commit is contained in:
Andrii Chubko 2021-09-05 10:23:14 +03:00
parent c6e2152c39
commit 6f46e27bb0
1 changed files with 40 additions and 6 deletions

View File

@ -9,6 +9,7 @@ import android.view.MotionEvent
import android.view.MotionEvent.INVALID_POINTER_ID
import android.view.ScaleGestureDetector
import android.view.View
import android.view.ViewConfiguration
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
@ -21,9 +22,13 @@ import com.simplemobiletools.draw.pro.models.MyPath
import com.simplemobiletools.draw.pro.models.PaintOptions
import java.util.*
import java.util.concurrent.ExecutionException
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val MIN_ERASER_WIDTH = 20f
private val mScaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
var mPaths = LinkedHashMap<MyPath, PaintOptions>()
var mBackgroundBitmap: Bitmap? = null
@ -57,6 +62,9 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
private var mScaleDetector: ScaleGestureDetector? = null
private var mScaleFactor = 1f
private var mLastMotionEvent: MotionEvent? = null
private var mTouchSloppedBeforeMultitouch: Boolean = false
init {
mPaint.apply {
color = mPaintOptions.color
@ -159,7 +167,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
.asBitmap()
.load(path)
.apply(options)
.into(size.x, size.y)
.submit(size.x, size.y)
mBackgroundBitmap = builder.get()
activity.runOnUiThread {
@ -264,7 +272,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
mScaleDetector!!.onTouchEvent(event)
}
val action = event.action and MotionEvent.ACTION_MASK
val action = event.actionMasked
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
mActivePointerId = event.getPointerId(0)
}
@ -295,7 +303,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
newValueY = scaledHeight * touchPercentageY - compensationY - (mPosY / mScaleFactor)
}
when (event.action and MotionEvent.ACTION_MASK) {
when (action) {
MotionEvent.ACTION_DOWN -> {
mWasMultitouch = false
mStartX = x
@ -307,6 +315,11 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
mListener?.toggleRedoVisibility(false)
}
MotionEvent.ACTION_MOVE -> {
if (mTouchSloppedBeforeMultitouch) {
mPath.reset()
mTouchSloppedBeforeMultitouch = false
}
if (!mAllowMovingZooming || (!mScaleDetector!!.isInProgress && event.pointerCount == 1 && !mWasMultitouch)) {
actionMove(newValueX, newValueY)
}
@ -324,9 +337,12 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
mActivePointerId = INVALID_POINTER_ID
actionUp()
}
MotionEvent.ACTION_POINTER_DOWN -> mWasMultitouch = true
MotionEvent.ACTION_POINTER_DOWN -> {
mWasMultitouch = true
mTouchSloppedBeforeMultitouch = mLastMotionEvent.isTouchSlop(pointerIndex, mStartX, mStartY)
}
MotionEvent.ACTION_POINTER_UP -> {
val upPointerIndex = (event.action and MotionEvent.ACTION_POINTER_INDEX_MASK shr MotionEvent.ACTION_POINTER_INDEX_SHIFT)
val upPointerIndex = event.actionIndex
val pointerId = event.getPointerId(upPointerIndex)
if (pointerId == mActivePointerId) {
val newPointerIndex = if (upPointerIndex == 0) 1 else 0
@ -337,6 +353,9 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
}
}
mLastMotionEvent = MotionEvent.obtain(event)
invalidate()
return true
}
@ -359,10 +378,25 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
pathsUpdated()
}
private fun MotionEvent?.isTouchSlop(pointerIndex: Int, startX: Float, startY: Float): Boolean {
return if (this == null || actionMasked != MotionEvent.ACTION_MOVE) {
false
} else {
try {
val moveX = abs(getX(pointerIndex) - startX)
val moveY = abs(getY(pointerIndex) - startY)
moveX <= mScaledTouchSlop && moveY <= mScaledTouchSlop
} catch (e: Exception) {
false
}
}
}
private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
mScaleFactor *= detector.scaleFactor
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f))
mScaleFactor = max(0.1f, min(mScaleFactor, 10.0f))
setBrushSize(mCurrBrushSize)
invalidate()
return true