CodeFlys
2/11/2020 - 1:18 AM

MultiTouchCoordinateView

class MultiTouchCoordinateView @JvmOverloads constructor(
    context: Context, @Nullable attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {

    companion object {
        private const val IMAGE_SIZE = 200F
    }

    private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var downX: Float = 0F
    private var downY: Float = 0F
    private var offsetX: Float = 0F
    private var offsetY: Float = 0F
    private var preOffsetX: Float = 0F
    private var preOffsetY: Float = 0F

    private val bitmap: Bitmap by lazy {
        getTargetWidthBitmap(dp2px(IMAGE_SIZE).toInt(), resources)!!
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawBitmap(bitmap, offsetX, offsetY, paint)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        var pointerCount = event.pointerCount
        var sunX: Float = 0F
        var sumY: Float = 0F
        var focusX: Float = 0F
        var focusY: Float = 0F
        for (i in 0 until pointerCount) {
            if (event.actionMasked != MotionEvent.ACTION_POINTER_UP || i != event.actionIndex) {
                sunX += event.getX(i)
                sumY += event.getY(i)
            }
        }
        if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) {
            pointerCount -= 1
        }
        focusX = sunX / pointerCount
        focusY = sumY / pointerCount

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                downX = focusX
                downY = focusY
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                offsetX = focusX - downX + preOffsetX
                offsetY = focusY - downY + preOffsetY
                invalidate()
            }
            MotionEvent.ACTION_POINTER_DOWN,
            MotionEvent.ACTION_POINTER_UP -> {
                downX = focusX
                downY = focusY
                preOffsetX = offsetX
                preOffsetY = offsetY
            }
            MotionEvent.ACTION_UP -> {
                preOffsetX = offsetX
                preOffsetY = offsetY
            }
        }
        return super.onTouchEvent(event)

    }

    private fun dp2px(dp: Float) = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,
        Resources.getSystem().displayMetrics
    )

    private fun getTargetWidthBitmap(targetWidth: Int, resources: Resources): Bitmap? {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
        options.inJustDecodeBounds = false
        options.inDensity = options.outWidth
        options.inTargetDensity = targetWidth
        return BitmapFactory.decodeResource(resources, R.drawable.wechat, options)
    }
}