Android 自定義View----多點觸摸反饋

多點觸摸和單點不同,只要瞭解每個觸摸點的屬性即可

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);
        }
    }
    
}

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章