多点触摸和单点不同,只要了解每个触摸点的属性即可
public class PaintingView extends View {
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 轻量级Map
SparseArray<Path> pathMap = new SparseArray<>();
public PaintingView(Context context) {
super(context);
}
public PaintingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public PaintingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
{
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(UnitUtil.dp2px(5));
// 设置画笔但始末端样式
mPaint.setStrokeCap(Paint.Cap.ROUND);
// 设置拐角样式
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
/*
多点触摸必须了解:
触摸事件针对view,不是针对point
每个触摸点都会有 x , y , index , id 四个属性:
① event.getX()等同于event.getX(0)
② event.getY()等同于event.getY(0)
③ index 用来遍历(会变) event.getActionIndex()
④ id 用来追踪(不会变) event.getPointerId(actionIndex)
假设第一个手指按下,第二个手指按下,第一个手指抬起:剩下的触摸点id不会边,index会变为0
连续三个手指触摸屏幕,第二个手指抬起然后再触摸屏幕:
第二个手指抬起,第三个手指的index会变为1,id不变
第二个手指再按下,第二个触摸点会根据id重新复用index为1,第三个手指index恢复2
*/
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
// 第一个手指,或者多手指 按下
case ACTION_DOWN:
case ACTION_POINTER_DOWN:
int actionIndex = event.getActionIndex();
// id是不变唯一的
int pointerId = event.getPointerId(actionIndex);
Path path = new Path();
path.moveTo(event.getX(actionIndex), event.getY(actionIndex));
pathMap.append(pointerId, path);
invalidate();
break;
case ACTION_MOVE:
for (int i = 0; i < event.getPointerCount(); i++) {
pointerId = event.getPointerId(i);
path = pathMap.get(pointerId);
path.lineTo(event.getX(i), event.getY(i));
}
invalidate();
break;
case ACTION_UP:
case ACTION_POINTER_UP:
pointerId = event.getPointerId(event.getActionIndex());
pathMap.remove(pointerId);
invalidate();
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 遍历所有 path 进行绘制
for (int i = 0; i < pathMap.size(); i++) {
Path path = pathMap.valueAt(i);
canvas.drawPath(path, mPaint);
}
}
}