Android 多点触控

三种类型 :接力型 /配合型 /单独型

单点触控

package com.example.myapplication.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.myapplication.dp

class MultiTouchView1(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private val bitmap = getBitmap()
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    private var offsetX = 0f //初始位置
    private var offsetY = 0f

    private var downX = 0f //按下的位置
    private var downY = 0f

    private var originalOffsetX = 0f //偏移位置
    private var originalOffsetY = 0f

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

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                downX = event.x
                downY = event.y
                originalOffsetX = offsetX
                originalOffsetY = offsetY

            }
            MotionEvent.ACTION_MOVE -> {
                offsetX = event.x - downX + originalOffsetX
                offsetY = event.y - downY + originalOffsetY
                invalidate()
            }
        }
        return true
    }
}

触摸事件序列是针对View而不是手指

x,y ,index ,id 属于一个point ,一个序列,getX 获取index为0的手指位置

  public final float getX() {
        return nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT);
    }

point_move 两个point,当第二根手指up,index会设置为0而不是1,有时候第0根手指down 为0index的会给按下的,然后0变为1

index作用是在发生MotionEvnent时,通过index遍历每个Point的操作

getX(),getX(index),index通过evnent.pointCount获取

for遍历event.point,通过getX(index) 如果某一个point抬起会报错 找不到Index,这时可以通过id查找

 MotionEvent.ACTION_MOVE -> {

                event.getX(event.actionIndex) //正在按下手指的ID
               event.getX(event.findPointerIndex(downId)) //通过ID获取
}

action_move 不适合这种方法,因为在实时移动 更新,没有所谓的Point 也就是index ,id,只有在down / up 才有意义

接力型

package com.example.myapplication.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.myapplication.dp


class MultiTouchView1(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private val bitmap =getBitmap()
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    private var offsetX = 0f //初始位置
    private var offsetY = 0f

    private var downX = 0f //按下的位置
    private var downY = 0f

    private var originalOffsetX = 0f //偏移位置
    private var originalOffsetY = 0f

    private var trackingPointerId = 0 //当前按下的手指ID

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

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                trackingPointerId = event.getPointerId(0)
                downX = event.x
                downY = event.y
                originalOffsetX = offsetX
                originalOffsetY = offsetY

            }

            //多个
            MotionEvent.ACTION_POINTER_DOWN -> {
                val actionIndex = event.actionIndex
                trackingPointerId = event.getPointerId(actionIndex) //按下的手指序号获取ID
                //更新 接管
                downX = event.getX(actionIndex)
                downY = event.getY(actionIndex)
                originalOffsetX = offsetX
                originalOffsetY = offsetY
            }

            MotionEvent.ACTION_POINTER_UP -> {
                val actionIndex = event.actionIndex
                val pointerId = event.getPointerId(actionIndex)
                if (pointerId == trackingPointerId) {
                    //如果是正在跟踪的手指 进行替换
                    val newIndex = if (actionIndex == event.pointerCount - 1) {
                            event.pointerCount - 2
                        } else {
                            event.pointerCount - 1
                        }

                    trackingPointerId = event.getPointerId(newIndex) //按下的手指序号获取ID
                    //更新 接管
                    downX = event.getX(newIndex)
                    downY = event.getY(newIndex)
                    originalOffsetX = offsetX
                    originalOffsetY = offsetY
                }
            }
            MotionEvent.ACTION_MOVE -> {

                val index = event.findPointerIndex(trackingPointerId)
                offsetX = event.getX(index) - downX + originalOffsetX
                offsetY = event.getY(index) - downY + originalOffsetY
                invalidate()
            }
        }
        return true
    }
}

配合型:

package com.example.myapplication.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.myapplication.dp
import com.example.myapplication.getAvatar


//双指滑动
class MultiTouchView2(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private val bitmap = getAvatar(resources, 200.dp.toInt())
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    private var offsetX = 0f //初始位置
    private var offsetY = 0f

    private var downX = 0f //按下的位置
    private var downY = 0f

    private var originalOffsetX = 0f //偏移位置
    private var originalOffsetY = 0f


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

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val focusX : Float//焦点 两值相加 /2
        val focusY : Float
        var pointerCount = event.pointerCount
        var sumX = 0f
        var sumY = 0f
        val inPointerUp = event.actionMasked == MotionEvent.ACTION_POINTER_UP //如果是抬起
        for (i in 0 until  pointerCount){
            if (!(inPointerUp && i == event.actionIndex)){ //当前位置并且不是抬起 则计算
                sumX += event.getX(i) //得到每个点的坐标
                sumY += event.getY(i)
            }
        }

        if (inPointerUp){
            pointerCount -- //处理额外偏移
        }
        focusX = sumX / pointerCount //得到焦点值 当抬起后count会变
        focusY = sumY /pointerCount

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN,MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_POINTER_UP -> {
                downX = focusX
                downY = focusY
                originalOffsetX = offsetX
                originalOffsetY = offsetY
            }

            MotionEvent.ACTION_MOVE -> {
                offsetX = focusX - downX + originalOffsetX
                offsetY = focusY - downY + originalOffsetY
                invalidate()
            }
        }
        return true
    }
}

多指

package com.example.myapplication.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.util.SparseArray
import android.view.MotionEvent
import android.view.View
import androidx.core.util.isEmpty
import com.example.myapplication.dp

class MultiTouchView3(context: Context, attrs: AttributeSet) : View(context, attrs) {
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var paths = SparseArray<Path>()

    init {
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 4.dp
        paint.strokeCap = Paint.Cap.ROUND
        paint.strokeJoin = Paint.Join.ROUND

    }
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        for (i in 0 until paths.size()){
            val path = paths.valueAt(i)
            canvas.drawPath(path,paint)
        }

    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when(event.actionMasked){

            MotionEvent.ACTION_DOWN,MotionEvent.ACTION_POINTER_DOWN ->{
                val actionIndex = event.actionIndex
                val path = Path()
                path.moveTo(event.getX(actionIndex),event.getY(actionIndex))
                paths.append(event.getPointerId(actionIndex),path)
                invalidate()
            }

            MotionEvent.ACTION_MOVE ->{
                if (!paths.isEmpty()){
                    for (i in 0 until paths.size()){
                        val pointerId = event.getPointerId(i)
                        val path = paths.get(pointerId)
                        path.lineTo(event.getX(i),event.getY(i))
                    }
                    invalidate()
                }

            }
            MotionEvent.ACTION_UP,MotionEvent.ACTION_POINTER_UP -> {
                val actionIndex = event.actionIndex
                val pointerId = event.getPointerId(actionIndex)
                paths.remove(pointerId)
                invalidate()
            }
        }


        return true
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值