4

我正在开发绘图应用程序,但面临一些撤消问题。编码如下:

public class DoodleView extends View 
{
    Context context_new;

    private static final float TOUCH_TOLERANCE = 5;
    private Bitmap bitmap; // drawing area for display or saving
    private Canvas bitmapCanvas; // used to draw on bitmap
    private Paint paintScreen; // use to draw bitmap onto screen
    private Paint paintLine; // used to draw lines onto bitmap

    private Path mPath; 
    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();
    private float mX, mY;

   // DoodleView constructor initializes the DoodleView
   public DoodleView(Context context, AttributeSet attrs) 
   {
       super(context, attrs); // pass context to View's constructor
       this.context_new=context;

       paintScreen = new Paint(); // used to display bitmap onto screen

       // set the initial display settings for the painted line
       paintLine = new Paint();
       paintLine.setAntiAlias(true); // smooth edges of drawn line
       paintLine.setColor(Color.BLACK); // default color is black
       paintLine.setStyle(Paint.Style.STROKE); // solid line

       mPath = new Path();
       paths.add(mPath);

   } // end DoodleView constructor

OnSizeChanged:

   @Override
   public void onSizeChanged(int w, int h, int oldW, int oldH)
   {
      super.onSizeChanged(w, h, oldW, oldH);
      DoodlzViewWidth = w;     
      DoodlzViewHeight = h;

      bitmap = Bitmap.createBitmap(getWidth(), DoodlzViewHeight, Bitmap.Config.ARGB_8888);

      bitmapCanvas = new Canvas(bitmap);
      bitmap.eraseColor(Color.WHITE); // erase the BitMap with white 
   } 

绘制:

   @Override
   protected void onDraw(Canvas canvas)  
   {
       canvas.drawBitmap(bitmap, 0, 0, paintScreen); 
       // for each path currently being drawn
       for (Path p : paths){canvas.drawPath(p, paintLine);}                
   } 

触摸事件:

   @Override
   public boolean onTouchEvent(MotionEvent event) 
   {          
          float x = event.getX();
          float y = event.getY();

          switch (event.getAction())
          {
              case MotionEvent.ACTION_DOWN:
                  touchStarted(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_MOVE:
                  touchMoved(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_UP:
                  touchEnded();
                  invalidate();
                  break;
          }
          return true;
    }

触摸开始:

   private void touchStarted(float x, float y) 
   {
       mPath.reset();
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
   }

触摸移动:

   private void touchMoved(float x, float y) 
   {
       float dx = Math.abs(x - mX);
       float dy = Math.abs(y - mY);
       if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) 
       {
           mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
           mX = x;
           mY = y;               
       }
   }

触摸结束:

   private void touchEnded() 
   {
      mPath.lineTo(mX, mY);      
      bitmapCanvas.drawPath(mPath, paintLine);
      mPath = new Path();
      paths.add(mPath);
      Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show();
   }

撤消:

public void onClickUndo() 
{ 
   Toast.makeText(getContext(), "before undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show();  
   if (paths.size()>0) 
    { 
       undonePaths.add(paths.remove(paths.size()-1));
       Toast.makeText(getContext(), "after undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show();
       Log.i("UNDOING", "PREPARE INVALIDATE");
       invalidate();
       Log.i("UNDOING", "FINISH INVALIDATE");
    }      
   else Toast.makeText(getContext(), "nothing to undo" + paths.size(), Toast.LENGTH_SHORT).show();  
}

问题:

以上内容来源于网上搜索的其他示例。不知道为什么需要在实现时设置 path.reset() touchStarted

Q1。当我按下撤消按钮时,它会正确显示已toast按下撤消按钮,并报告path.size()为 0,因此不会删除之前立即绘制的线。我真的不知道为什么它是0?它不是已经添加到路径数组中了吗?如何修改代码?

** 代码在采纳 android-developer 的建议后修改!谢谢!!它现在正确显示 path.size()。对不起,愚蠢的错过了!*但是之前绘制的线仍然无法删除?=(

Q2。当手指在屏幕上移动并立即显示线条时应用程序正常运行,当我按下撤消按钮时,除了上面没有删除上一行之外,线条在按下后进一步绘制到屏幕上直到手指抬起按钮才会显示出来。

回答 Q2: 将以下 2 行touchEnded()touchStarted()

mPath = new Path();
paths.add(mPath);

.

   private void touchStarted(float x, float y) 
   {
       mPath.reset();
       mPath = new Path();
       paths.add(mPath);
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
   }

   private void touchEnded() 
   {
       mPath.lineTo(mX, mY);      
       bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen                   
       Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show();
   }

谢谢!!!

4

1 回答 1

4

更新和工作:

  1. 删除了油漆paintScreen;
  2. 在 onDraw 中不要放canvas.drawBitmap(bitmap, 0, 0, paintScreen);canvas.drawBitmap(bitmap, 0, 0, paintLine);

    private Bitmap bitmap; // drawing area for display or saving
    private Canvas bitmapCanvas; // used to draw on bitmap
    private Paint paintLine; // used to draw lines onto bitmap   
    private Path mPath; 
    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();
    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;    
    
    // DoodleView constructor initializes the DoodleView
    
    public DoodleView(Context context, AttributeSet attrs) 
    {
       super(context, attrs); // pass context to View's constructor
       this.context_new=context;
       setFocusable(true);
       setFocusableInTouchMode(true);      
    
       // set the initial display settings for the painted line
       paintLine = new Paint();
       paintLine.setAntiAlias(true); // smooth edges of drawn line
       paintLine.setDither(true);
       paintLine.setColor(Color.BLACK); // default color is black
       paintLine.setStyle(Paint.Style.STROKE); // solid line
       paintLine.setStrokeJoin(Paint.Join.ROUND);
       paintLine.setStrokeWidth(5); // set the default line width
       paintLine.setStrokeCap(Paint.Cap.ROUND); // rounded line ends
    
       bitmapCanvas = new Canvas();
       mPath = new Path();            
     } // end DoodleView constructor
    
     // Method onSizeChanged creates BitMap and Canvas after app displays
    
     @Override
     public void onSizeChanged(int w, int h, int oldW, int oldH)
     {
        super.onSizeChanged(w, h, oldW, oldH);
        DoodlzViewWidth = w;       
        DoodlzViewHeight = h;           
     } 
    
     @Override
    
     protected void onDraw(Canvas canvas) 
     {         
       for (Path p : paths){canvas.drawPath(p, paintLine);}  
       canvas.drawPath(mPath, paintLine);
       Log.i("OnDRAWING", "REACH ON DRAW");        
    } 
    

    // START TOUCH: 处理触摸事件 @Override

     public boolean onTouchEvent(MotionEvent event) 
     {            
          float x = event.getX();
          float y = event.getY();
    
          switch (event.getAction())
          {
              case MotionEvent.ACTION_DOWN:
                  touch_start(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_MOVE:
                 touch_move(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_UP:
                  touch_up();
                  invalidate();
                  break;
          }
          return true;
    }
    
     private void touch_start(float x, float y) 
     {
       undonePaths.clear();
       mPath.reset();
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
    }
    
    private void touch_move(float x, float y) 
    {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) 
        {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }  
    
    private void touch_up() 
    {
        mPath.lineTo(mX, mY);      
        bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen  
        paths.add(mPath);
        mPath = new Path(); 
    }
    
    public void onClickUndo() 
    { 
       if (paths.size()>0) 
        { 
           undonePaths.add(paths.remove(paths.size()-1));
           invalidate();
        }      
       else Toast.makeText(getContext(), "nothing more to undo", Toast.LENGTH_SHORT).show();  
    }
    
于 2013-02-26T16:22:30.963 回答