2016-09-03 16 views
0

所以我目前正在爲學校項目創建一個簡單的繪畫應用程序,部分原因是它的方式非常有趣,我試圖確保通過閱讀獲取所有觸摸事件通過直到今天我嘗試添加多點觸摸的歷史,現在使用一個手指進行繪圖是很好的,但是當您開始使用另一個時,Action_Down不會運行,導致繪製一條隨機線。這裏是我的代碼:android沒有在第二個指針上註冊動作

package com.sciguy.paint; 

import android.app.ProgressDialog; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.os.Handler; 
import android.os.Message; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 

import java.util.List; 
import java.util.concurrent.CopyOnWriteArrayList; 


public class DrawingView extends View { 

    private Paint drawPaint; 

    private static Canvas drawCanvas; 

    private List<Point> points = new CopyOnWriteArrayList<>(); 

    private List<Point> oldPoints = new CopyOnWriteArrayList<>(); 

    public DrawingView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setFocusable(true); 
     setFocusableInTouchMode(true); 
     drawPaint = new Paint(); 
     drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); 
     drawPaint.setColor(CommonResources.getColor()); 
     drawPaint.setAntiAlias(false); 
     drawPaint.setStrokeWidth(CommonResources.size); 
     drawPaint.setStyle(Paint.Style.STROKE); 
     drawPaint.setStrokeJoin(Paint.Join.ROUND); 
     drawPaint.setStrokeCap(Paint.Cap.ROUND); 
     if (CommonResources.oldThread == null) { 
      CommonResources.oldThread = DrawBitmap; 
      DrawBitmap.start(); 
     } else { 
      CommonResources.stopThread = true; 
      //noinspection SynchronizeOnNonFinalField 
      synchronized (CommonResources.oldThread) { 
       CommonResources.oldThread.notify(); 
      } 
      //noinspection StatementWithEmptyBody 
      while (CommonResources.stopThread) ; 
      CommonResources.oldThread = DrawBitmap; 
      DrawBitmap.start(); 
     } 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     if (CommonResources.canvasBitmap == null) { 
      CommonResources.canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     } 
     drawCanvas = new Canvas(CommonResources.canvasBitmap); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     canvas.drawBitmap(CommonResources.canvasBitmap, 0, 0, null); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     float curX = event.getX(); 
     float curY = event.getY(); 
     if (CommonResources.fill) { 
      if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 
       if (!CommonResources.isFillThreadRunning) { 
        new FloodFillThread(ProgressDialog.show(getContext(), "Flood Fill", "Filling Area..."), handler, CommonResources.canvasBitmap, new android.graphics.Point((int) curX, (int) curY), CommonResources.canvasBitmap.getPixel((int) curX, (int) curY), CommonResources.getColor()).start(); 
       } 
       return true; 
      } 
      return true; 
     } else { 
      Point point; 
      if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 
       point = new Point(); 
       curX = event.getX(event.getActionIndex()); 
       curY = event.getY(event.getActionIndex()); 
       point.oldX = curX; 
       point.oldY = curY; 
       addOldPoint(curX, curY, event.getActionIndex()); 
      } else { 
       for (int h = 0; h < event.getHistorySize(); h++) { 
        for (int i = 0; i < event.getPointerCount(); i++) { 
         curX = event.getHistoricalX(i, h); 
         curY = event.getHistoricalY(i, h); 
         point = getOldPoint(i); 
         point.newX = curX; 
         point.newY = curY; 
         addOldPoint(curX, curY, i); 
         points.add(point); 
         updateBitmap(); 
        } 
       } 
      } 
     } 
     return true; 
    } 


    public static void clearScreen() { 
     CommonResources.canvasBitmap.eraseColor(Color.TRANSPARENT); 
    } 

    public void updateBitmap() { 
     synchronized (DrawBitmap) { 
      DrawBitmap.notify(); 
     } 
    } 

    final Thread DrawBitmap = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (!CommonResources.stopThread) { 
       for (Point p : points) { 
        drawCanvas.drawLine(p.oldX, p.oldY, p.newX, p.newY, drawPaint); 
        points.remove(p); 
        postInvalidate(); 
       } 
       try { 
        synchronized (DrawBitmap) { 
         DrawBitmap.wait(); 
        } 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      CommonResources.stopThread = false; 
     } 
    }); 

    private class Point { 
     float newX, newY, oldX, oldY; 
     int id; 

     @Override 
     public String toString() { 
      return newX + ", " + newY + ", " + oldX + ", " + oldY; 
     } 
    } 

    private void addOldPoint(float x, float y, int id) { 
     for (Point p : oldPoints) { 
      if (p.id == id) { 
       oldPoints.remove(p); 
      } 
     } 
     Point p = new Point(); 
     p.oldX = x; 
     p.oldY = y; 
     p.id = id; 
     oldPoints.add(p); 
    } 

    private Point getOldPoint(int id) { 
     for (Point p : oldPoints) { 
      if (p.id == id) { 
       return p; 
      } 
     } 

     return new Point(); 
    } 

    Handler handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      if (msg.what == 0) { 
       postInvalidate(); 
      } 
     } 
    }; 

    public static void updateCanvas() { 
     drawCanvas = new Canvas(CommonResources.canvasBitmap); 
    } 

} 

這是視圖代碼,它主要是自我解釋然而這裏反正是幾件事情。 CommonResources是一個簡單的類,它包含一些全局變量,這些變量需要在活動交換(位圖,繪畫顏色等)之間保留。線程用於繪製位圖以節省ondraw方法的時間。並且有一個正在工作的填充函數,但是爲了這個問題,請忽略對它的任何引用(無論如何,它都在另一個類中)。如果需要更多的代碼或說明,我會很樂意提供。

感謝,Sciguy

回答

0

嗯,我只是想通了,這裏的更新代碼:

package com.sciguy.paint; 

import android.app.ProgressDialog; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.os.Handler; 
import android.os.Message; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 

import java.util.List; 
import java.util.concurrent.CopyOnWriteArrayList; 


public class DrawingView extends View { 

    private Paint drawPaint; 

    private static Canvas drawCanvas; 

    private List<Point> points = new CopyOnWriteArrayList<>(); 

    private List<Point> oldPoints = new CopyOnWriteArrayList<>(); 

    public DrawingView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setFocusable(true); 
     setFocusableInTouchMode(true); 
     drawPaint = new Paint(); 
     drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); 
     drawPaint.setColor(CommonResources.getColor()); 
     drawPaint.setAntiAlias(false); 
     drawPaint.setStrokeWidth(CommonResources.size); 
     drawPaint.setStyle(Paint.Style.STROKE); 
     drawPaint.setStrokeJoin(Paint.Join.ROUND); 
     drawPaint.setStrokeCap(Paint.Cap.ROUND); 
     if (CommonResources.oldThread == null) { 
      CommonResources.oldThread = DrawBitmap; 
      DrawBitmap.start(); 
     } else { 
      CommonResources.stopThread = true; 
      //noinspection SynchronizeOnNonFinalField 
      synchronized (CommonResources.oldThread) { 
       CommonResources.oldThread.notify(); 
      } 
      //noinspection StatementWithEmptyBody 
      while (CommonResources.stopThread) ; 
      CommonResources.oldThread = DrawBitmap; 
      DrawBitmap.start(); 
     } 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     if (CommonResources.canvasBitmap == null) { 
      CommonResources.canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     } 
     drawCanvas = new Canvas(CommonResources.canvasBitmap); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     canvas.drawBitmap(CommonResources.canvasBitmap, 0, 0, null); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     float curX = event.getX(); 
     float curY = event.getY(); 
     if (CommonResources.fill) { 
      if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 
       if (!CommonResources.isFillThreadRunning) { 
        new FloodFillThread(ProgressDialog.show(getContext(), "Flood Fill", "Filling Area..."), handler, CommonResources.canvasBitmap, new android.graphics.Point((int) curX, (int) curY), CommonResources.canvasBitmap.getPixel((int) curX, (int) curY), CommonResources.getColor()).start(); 
       } 
       return true; 
      } 
      return true; 
     } else { 
      Point point; 
      switch (event.getActionMasked()) { 
       case MotionEvent.ACTION_DOWN: 
       case MotionEvent.ACTION_POINTER_DOWN: 
        point = new Point(); 
        curX = event.getX(event.getActionIndex()); 
        curY = event.getY(event.getActionIndex()); 
        point.oldX = curX; 
        point.oldY = curY; 
        addOldPoint(curX, curY, event.getPointerId(event.getActionIndex())); 

        break; 
       case MotionEvent.ACTION_MOVE: 
        for (int h = 0; h < event.getHistorySize(); h++) { 
         for (int i = 0; i < event.getPointerCount(); i++) { 
          curX = event.getHistoricalX(i, h); 
          curY = event.getHistoricalY(i, h); 
          point = getOldPoint(event.getPointerId(i)); 
          point.newX = curX; 
          point.newY = curY; 
          addOldPoint(curX, curY, event.getPointerId(i)); 
          points.add(point); 
          updateBitmap(); 
         } 
        } 

        break; 
       case MotionEvent.ACTION_UP: 
       case MotionEvent.ACTION_POINTER_UP: 
        curX = event.getX(event.getActionIndex()); 
        curY = event.getY(event.getActionIndex()); 
        point = getOldPoint(event.getPointerId(event.getActionIndex())); 
        point.newX = curX; 
        point.newY = curY; 
        points.add(point); 
        updateBitmap(); 

        break; 

      } 
     } 
     return true; 
    } 



    public static void clearScreen() { 
     CommonResources.canvasBitmap.eraseColor(Color.TRANSPARENT); 
    } 

    public void updateBitmap() { 
     synchronized (DrawBitmap) { 
      DrawBitmap.notify(); 
     } 
    } 

    final Thread DrawBitmap = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (!CommonResources.stopThread) { 
       for (Point p : points) { 
        drawCanvas.drawLine(p.oldX, p.oldY, p.newX, p.newY, drawPaint); 
        points.remove(p); 
        postInvalidate(); 
       } 
       try { 
        synchronized (DrawBitmap) { 
         DrawBitmap.wait(); 
        } 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      CommonResources.stopThread = false; 
     } 
    }); 

    private class Point { 
     float newX, newY, oldX, oldY; 
     int id; 

     @Override 
     public String toString() { 
      return newX + ", " + newY + ", " + oldX + ", " + oldY; 
     } 
    } 

    private void addOldPoint(float x, float y, int id) { 
     for (Point p : oldPoints) { 
      if (p.id == id) { 
       oldPoints.remove(p); 
      } 
     } 
     Point p = new Point(); 
     p.oldX = x; 
     p.oldY = y; 
     p.id = id; 
     oldPoints.add(p); 
    } 

    private Point getOldPoint(int id) { 
     for (Point p : oldPoints) { 
      if (p.id == id) { 
       return p; 
      } 
     } 

     return new Point(); 
    } 

    Handler handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      if (msg.what == 0) { 
       postInvalidate(); 
      } 
     } 
    }; 

    public static void updateCanvas() { 
     drawCanvas = new Canvas(CommonResources.canvasBitmap); 
    } 

} 

變化:

我添加了一個開關的情況下(這是有,但在調試情況下,它有已被刪除),我同時使用了MotionEvent.ACTION_UP和MotionEvent.ACTION_POINTER_UP(分別存在不同的變體),這兩個問題都導致了一個問題,現在所有的Action_up和Downs都被調用,但是指針ID被設置爲最低位置如果P1 = 0,並且P2 = 1,則當指針P1被移除時,P2變爲0,從而導致從第一指針的最後一個知道位置到第二指針的當前位置畫出不必要的行。所以要解決這個問題,而不是使用event.getActionIndex保存到oldPoints我使用event.getPointerId(event.getActionIndex())女巫返回了一個唯一的ID並解決了我的最後一個問題。

感謝所有誰看了我的問題,我知道17做:) 如果將來你需要任何澄清隨意問

-Sciguy

相關問題