【问题标题】:android (singletouch) drawing app undo method not working properlyandroid(单点触控)绘图应用程序撤消方法无法正常工作
【发布时间】:2013-02-04 06:59:43
【问题描述】:

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

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 
   } 

onDraw:

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

onTouchEvent:

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

touchStarted:

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

touchEnded:

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

问题:

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

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

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

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

回答问题 2: 将以下 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();
   }

谢谢!!!

【问题讨论】:

  • mPath.reset(); 之后我看不到 paths.add(mPath);。您在哪里将当前路径添加到您的数组列表?
  • 感谢您的建议!!我已经修正了愚蠢的遗漏错误! path.size() 现在可以正确显示,即。当再画一条线时,尺寸会增加1。但是之前的路径仍然无法删除(虽然toast undo显示),并且按下按钮时奇怪的绘制效果:绘制时线条不会出现,直到手指被移除。
  • 你是说即使paths.size() 大于0,undo button pressed toast 也会出现?
  • 撤消部分编码已更新。如果绘制了 4 条线,它将显示“撤消按钮已按下 4”。感谢您的及时回复~
  • 你能帮我检查一下吗,按下撤消按钮后它实际上是从数组列表中删除最后一个路径吗?如果在invalidate() 之后调用onDraw() 方法?

标签: android canvas path bitmap touch-event


【解决方案1】:

更新和工作:

  1. 已移除 Paint 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-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2016-03-19
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多