自定义 View:多点触控 (三)-- 各自为战

本篇为系列文章
一个跟随手指滑动的图片 – 单点触摸
自定义 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
    }

}

你可能感兴趣的:(#,触摸反馈,android)