Android多点触控问题

触摸事件类型

单点触控相关:

  • ACTION_DOWN
    当用户首次触摸屏幕时触发,表示触摸的开始。通常是触摸事件的起点。
  • ACTION_MOVE
    当用户在屏幕上移动手指时触发,表示触摸点位置发生变化。
  • ACTION_UP
    当用户抬起手指时触发,表示触摸结束。
  • ACTION_CANCEL
    当触摸事件被取消时触发,例如父 View 拦截了事件或系统中止了触摸。

多点触控相关:

  • ACTION_POINTER_DOWN
    当屏幕上已有触摸点时,另一个手指按下触发,表示新增了一个触摸点。
  • ACTION_POINTER_UP
    当屏幕上有多个触摸点时,其中一个手指抬起触发,表示某个触摸点结束。

多点触控处理相关方法

  • event.getActionMasked():返回当前的触摸事件类型(包含单点触控和多点触控)。
  • event.getActionIndex():返回多点触控事件中当前新增触摸点或当前移除触摸点的索引(适用于ACTION_POINTER_DOWN和ACTION_POINTER_UP多点触控相关事件)。
  • getPointerId(int index):根据指定索引返回对应触摸点的唯一ID。
  • getX(int index)和getY(int index):返回指定索引的触摸点的X和Y坐标。
  • getPointerCount():返回当前触摸点的数量。
  • findPointerIndex(int pointerId):根据ID查找触摸点当前索引。

触摸点的索引与ID

  • 索引:触摸点的编号,从0开始,最大值为getPointerCount()-1。但索引是动态的,会因触摸点的抬起而改变。
  • ID:每个触摸点的唯一标识符,在其生命周期内固定不变。因此,ID是跟踪特定触摸点的可靠依据。

例如:一个手指按下,索引为0,ID为0。第二个手指按下,索引为1,ID为1。第一个手指抬起,那么第二个手指的索引变为0,但ID仍为1。

处理多点触控的步骤

1.记录新触摸点

ACTION_DOWN:第一个触摸点按下,记录第一个触摸点的ID和位置(此时ID为0),并添加到Map中。

ACTION_POINTER_DOWN:新增触摸点按下,记录其ID和位置(此时通过getActionIndex()获取新增触摸点的索引,然后将该索引传入getPointerId()中得到对应的触摸点ID;将索引传入getX、getY中得到触摸点位置),并添加到Map中。

2.更新触摸点

ACTION_MOVE:遍历所有触摸点(i in 0..getPointerCount()-1),更新它们的当前位置。

3.移除触摸点

ACTION_POINTER_UP:某个触摸点抬起,获取该触摸点ID(此时通过getActionIndex()获取移除触摸点的索引,然后将该索引传入getPointerId()中得到对应的触摸点ID),在Map中移除。

ACTION_UP:最后一个触摸点抬起,结束整个触摸过程。

实际代码理解

class TouchView(context: Context) : View(context) {
    // 使用MutableMap存储触摸点ID和对应的(X, Y)坐标
    private val touchPoints = mutableMapOf<Int, Pair<Float, Float>>()
    private val paint = Paint().apply {
        color = 0xFF0000FF.toInt() // 蓝色
        style = Paint.Style.FILL
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // 第一个触摸点按下
                val id = event.getPointerId(0)
                val x = event.getX(0)
                val y = event.getY(0)
                touchPoints[id] = Pair(x, y)
            }
            MotionEvent.ACTION_POINTER_DOWN -> {
                // 新的触摸点按下
                val index = event.actionIndex
                val id = event.getPointerId(index)
                val x = event.getX(index)
                val y = event.getY(index)
                touchPoints[id] = Pair(x, y)
            }
            MotionEvent.ACTION_MOVE -> {
                // 触摸点移动,更新所有触摸点位置
                for (i in 0 until event.pointerCount) {
                    val id = event.getPointerId(i)
                    val x = event.getX(i)
                    val y = event.getY(i)
                    touchPoints[id] = Pair(x, y)
                }
            }
            MotionEvent.ACTION_POINTER_UP -> {
                // 某个触摸点抬起,移除该触摸点
                val index = event.actionIndex
                val id = event.getPointerId(index)
                touchPoints.remove(id)
            }
            MotionEvent.ACTION_UP -> {
                // 最后一个触摸点抬起,清空Map
                touchPoints.clear()
            }
            MotionEvent.ACTION_CANCEL -> {
                // 触摸事件取消,清空Map
                touchPoints.clear()
            }
        }
        // 触发重绘
        invalidate()
        return true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 绘制每个触摸点
        for ((_, point) in touchPoints) {
            canvas.drawCircle(point.first, point.second, 50f, paint)
        }
    }
}

总结

多点触控的处理是通过 onTouchEvent 方法中的事件(如 ACTION_DOWN、ACTION_POINTER_DOWN、ACTION_MOVE、ACTION_POINTER_UP、ACTION_UP),利用触摸点的唯一 ID 来管理其记录、更新和移除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值