2016-09-03 5 views
0

私は現在、学校のプロジェクトのために部分的に単純なペイントアプリを作成していますが、それは楽しいところですから、私はすべてのタッチイベントを読む今日まで私がマルチタッチを追加しようとしたときまで働いていた歴史を通して、今では1本の指で描くのはいいですが、別のものを使い始めると、Action_Downが実行されず、ランダムな線が引かれます。ここに私のコードは次のとおりです。アンドロイドは2番目のポインタにアクションを登録していません

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は最低位のposつまり、P1 = 0であり、P2 = 1である場合、ポインタP1が除去されたときにP2が0になると、第1ポインタの最後の既知の位置から第2ポインタの現在の位置まで不要な線が引かれていた。ですから、event.getActionIndexをoldPointsに保存する代わりに、event.getPointerId(event.getActionIndex())を使用して魔女が一意のIDを返し、最後の問題を修正しました。任意の明確化が

-Sciguy

気軽にあなたが必要とする将来の場合は私の問題を見てすべての人へ

おかげで、私は17 :) をした知っています

関連する問題