本篇为系列文章
一个跟随手指滑动的图片 – 单点触摸
自定义 View:多点触控 (一)-- 手指接力
自定义View:多点触控(二)-- 多指协作
自定义 View:多点触控 (三)-- 各自为战
这种情况不是很少的奇葩使用场景,只是比较少而已,还是有这种需求的,比如说一个画板功能,就需要每个手指去做自己的事情
那好,我们就来一步步实现一个画板的功能
展示基础代码
package com.example.viewtest.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.viewtest.ext.dp
class MultiTouchView3 (context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val path = Path()
init {
// 粗笔
paint.style = Paint.Style.STROKE
// 笔迹宽
paint.strokeWidth = 4.dp(context)
// 圆角
paint.strokeCap = Paint.Cap.ROUND
// 圆角
paint.strokeJoin = Paint.Join.ROUND
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawPath(path, paint)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
return true
}
}
既然是画线,那我们需要drawPath,然后需要画笔paint,还有经过的路径要记录下来path
接下来就是记录手指移动的路径,在落下、移动时记录下,仅做演示使用,在手指抬起的时候进行清空
我们先来实现一个单指的效果
override fun onTouchEvent(event: MotionEvent): Boolean {
when(event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
path.moveTo(event.x, event.y)
invalidate()
}
MotionEvent.ACTION_MOVE -> {
path.lineTo(event.x, event.y)
invalidate()
}
MotionEvent.ACTION_UP -> {
path.reset()
invalidate()
}
}
return true
}
OK,以上就完成了,接下来我们实现多指的效果
多指就意味着需要记录多指的路径,这里使用SparseArray来记录,比较简单,直接贴最终代码
package com.example.viewtest.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 com.example.viewtest.ext.dp
class MultiTouchView3 (context: Context, attrs: AttributeSet?) : View(context, attrs) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val paths = SparseArray<Path>()
init {
// 粗笔
paint.style = Paint.Style.STROKE
// 笔迹宽
paint.strokeWidth = 4.dp(context)
// 圆角
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 -> {
for (i in 0 until paths.size()) {
val path = paths.get(event.getPointerId(i))
path.lineTo(event.getX(i), event.getY(i))
}
invalidate()
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
paths.remove(event.getPointerId(event.actionIndex))
invalidate()
}
}
return true
}
}