三种类型 :接力型 /配合型 /单独型
单点触控
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
}
}