多點觸摸和單點不同,只要瞭解每個觸摸點的屬性即可
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);
}
}
}