保存新图像时,它会保留旧画布

时间:2013-09-05 16:02:39

标签: java android android-canvas

我有一个允许用户绘制和保存的画布。它还允许用户更改颜色并在不同颜色的同一画布上绘制。

我的Paint类:

package com.test.testing;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.test.testing.*;

public class CustomView extends View {
    Paint paint;
    Path path;
    float x = 0;
    float y = 0;
    private int cWhite = Color.WHITE;
    private Button btnS, btnSa;

    public CustomView(Context context) {
        super(context);
        paint = new Paint();
        path= new Path();
        paint.setAlpha(255);
        paint.setColor(cWhite);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(20);

        btnS = (Button)((FreeDraw) context).findViewById(R.id.shareButton);
        btnSa = (Button)((FreeDraw) context).findViewById(R.id.saveButton);
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(path,paint);
        canvas.drawCircle(x, y, 10, paint);
    }

    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            path.moveTo(event.getX(), event.getY());
            path.lineTo(event.getX(), event.getY());
            if (btnS.getVisibility() == View.VISIBLE && btnS != null) {
                //if share button is displaying but I drew something else
                //the share button should disappear and I should be presented
                //with the save button

                btnS.setVisibility(View.GONE);
                btnSa.setVisibility(View.VISIBLE);
            }
            if (btnSa.getVisibility() == View.VISIBLE && btnS != null) {
                //do nothing...
            }
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            x = event.getX();
            y = event.getY();
            path.lineTo(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            path.lineTo(event.getX(), event.getY());
            invalidate();
            break;
        case MotionEvent.ACTION_CANCEL:
            break;
        default:
            break;
        }
        return true;
    }
}

在我的Activity中,我调用Paint类并使用如下的XML布局:

layout = (FrameLayout)findViewById(R.id.viewd);
//layout.removeAllViews();
view = new CustomView(FreeDraw.this);
view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
layout.addView(view);

同样在同一个活动中,我有以下代码来处理颜色变化:

public void colorHandle() {
    // custom dialog
    final Dialog dialog = new Dialog(this);
    dialog.setContentView(R.layout.colorlayout);
    dialog.setTitle("Choose a Drawing Color");

    Button btnWH = (Button) dialog.findViewById(R.id.btnWhite);
    Button btnBL = (Button) dialog.findViewById(R.id.btnBlack);
    Button btnBLU = (Button) dialog.findViewById(R.id.btnBlue);
    Button btnCY = (Button) dialog.findViewById(R.id.btnCyan);
    Button btnDG = (Button) dialog.findViewById(R.id.btnDkGray);
    Button btnGR = (Button) dialog.findViewById(R.id.btnGray);
    Button btnGRE = (Button) dialog.findViewById(R.id.btnGreen);
    Button btnLG = (Button) dialog.findViewById(R.id.btnLtGray);
    Button btnMG = (Button) dialog.findViewById(R.id.btnMagenta);
    Button btnRD = (Button) dialog.findViewById(R.id.btnRed);
    Button btnYE = (Button) dialog.findViewById(R.id.btnYellow);

    if (btnWH != null) {
        btnWH.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.WHITE);
                dialog.dismiss();
            }
        });
    }
    if (btnBL != null) {
        btnBL.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.BLACK);
                dialog.dismiss();
            }
        });
    }
    if (btnBLU != null) {
        btnBLU.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.BLUE);
                dialog.dismiss();
            }
        });
    }
    if (btnCY != null) {
        btnCY.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.CYAN);
                dialog.dismiss();
            }
        });
    }
    if (btnDG != null) {
        btnDG.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.DKGRAY);
                dialog.dismiss();
            }
        });
    }
    if (btnGR != null) {
        btnGR.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.GRAY);
                dialog.dismiss();
            }
        });
    }
    if (btnGRE != null) {
        btnGRE.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.GREEN);
                dialog.dismiss();
            }
        });
    }
    if (btnLG != null) {
        btnLG.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.LTGRAY);
                dialog.dismiss();
            }
        });
    }
    if (btnMG != null) {
        btnMG.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.MAGENTA);
                dialog.dismiss();
            }
        });
    }
    if (btnRD != null) {
        btnRD.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.RED);
                dialog.dismiss();
            }
        });
    }
    if (btnYE != null) {
        btnYE.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                layout = (FrameLayout)findViewById(R.id.viewd);
                //layout.removeAllViews();
                view = new CustomView(FreeDraw.this);
                view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
                layout.addView(view);
                view.paint.setColor(Color.YELLOW);
                dialog.dismiss();
            }
        });
    }
    dialog.show();
}

我必须为每种颜色重复以下代码,因为一旦我绘制了一些内容并更改了颜色并绘制了其他内容,所有之前绘制的路径都会更改为新颜色并且此代码修复了它:

        layout = (FrameLayout)findViewById(R.id.viewd);
        //layout.removeAllViews();
        view = new CustomView(FreeDraw.this);
        view.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
        layout.addView(view);

活动中代码的保存图片部分是:

View.OnClickListener saveHandle = new View.OnClickListener() {
    public void onClick(View v) {
        new SaveImageTask().execute(null, null, null);
    }
};
public class SaveImageTask extends AsyncTask<Void, Void, Void> {
     @Override
     protected Void doInBackground(Void... params) { //Running in background
        View content = layout;
        content.setDrawingCacheEnabled(true);
        content.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        Bitmap bitmap = content.getDrawingCache();
        File folder = new File(Environment.getExternalStorageDirectory() + "/PB");
        if (!folder.exists()) {
            folder.mkdir();
        }
        file = new File(folder + "/pb_image_" + Math.random()  + ".png");
        FileOutputStream ostream;
        try {
            file.createNewFile();
            ostream = new FileOutputStream(file);
            bitmap.compress(CompressFormat.PNG, 100, ostream);
            ostream.flush();
            ostream.close();
            isSaved = true;
        } catch (Exception e) {
            e.printStackTrace();
            isSaved = false;
        }
        return null;
     }

     @Override
     protected  void onPreExecute() { //Activity is on progress
         //displayToast("Your image is saving...");
         btnSave.setVisibility(View.GONE);
         btnShare.setVisibility(View.GONE);
         pb.setVisibility(View.VISIBLE);
     }

     @Override
     protected void onPostExecute(Void v) { //Activity is done...
        if (isSaved == true) {
             displayToast("Image was saved.");
             btnSave.setVisibility(View.GONE);
             btnShare.setVisibility(View.VISIBLE);
             pb.setVisibility(View.GONE);
         }
         if (isSaved == false) {
             displayToast("Unable to save image. Try again later.");
             btnSave.setVisibility(View.VISIBLE);
             btnShare.setVisibility(View.GONE);
             pb.setVisibility(View.GONE);
         }
     }
}

我期待的是:

  • 当我画一些东西并保存图像时,应该出现SHARE按钮并且Canvas不应该清除(工作)
  • 当SHARE按钮可见时,我在画布上画了其他东西,SAVE按钮应该重新出现(工作)
  • 当我再次按下SAVE按钮时,它应该保存新的画布图(不工作,它保存了我在第一步保存的先前绘制的画布

如何修改代码才能执行此操作

  • 不要为每种颜色创建新画布,而是创建新路径。
  • 保存画布上的绘图后,我会在现有画布上绘制新内容并保存。新画布应与所有旧的和新绘制的路径一起保存
  • 如果按下ERASE按钮,则清除整个画布

1 个答案:

答案 0 :(得分:3)

  

不要为每种颜色创建新画布,而是创建新路径。

为用户触摸画布的每个新时间创建Path,理论上绘制一些东西。存储新路径及其颜色并在onDraw方法中迭代路径结构并使用其保存的颜色绘制每个路径:

// this will hold the data of each path the user draws
class DrawnItem {
    int color = Color.GREEN; // default values
    Path line = new Path();
}

Paint paint;
int mCurrentColor = Color.GREEN; // start with green
ArrayList<DrawnItem> mDrawings = new ArrayList<DrawnItem>();

// in the onDraw method:
protected void onDraw(Canvas canvas) {
    final int count = mDrawings.size();
    for (int i = 0; i < count; i++) {
        final DrawnItem item = mDrawings.get(i);
        paint.setColor(item.color);
        canvas.drawPath(item.line, paint);
    }
    paint.setColor(mCurrentColor);
    canvas.drawCircle(x, y, 10, paint);
}

private DrawnItem mCurrentItem = null;

// and in the onTouch method:
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
       // the user started a new drawing so build a new DrawnItem
       mCurrentItem = new DrawnItem();
       mCurrentitem.color= mCurrentColor;  
       mDrawings.add(mCurrentItem);
       // use the item.line to setup the Path with the x and y values
       // .... 
       invalidate();
       break; 
       case MotionEvent.ACTION_MOVE:
           x = event.getX();
           y = event.getY();
           mCurrentItem.line.lineTo(x, y);
           invalidate();
       break;
    case MotionEvent.ACTION_UP:
        mCurrentItem.line.lineTo(event.getX(), event.getY());
        mCurrentItem = null;
        invalidate();
        break;
    case MotionEvent.ACTION_CANCEL:
        mCurrentItem = null; // this drawing session was canceled so this DrawnItem is now closed
        break;
    default:
        break;

现在,在对话框中,您唯一需要做的就是将自定义视图的mCurrentColor更新为所选颜色的点,并且将使用专用颜色绘制路径上的该点。如果用户将颜色切换为先前存储的颜色,则将选择与该颜色对应的路径。

将视图保存为doInBackground()中的Bitmap的代码:

Bitmap bitmap = Bitmap.createBitmap(layout.getWidth(), layout.getHeight(), Bitmap.Config. RGB_565);
Canvas canvas = new Canvas(bitmap);
layout.draw(canvas);
  

如果按下ERASE按钮,则清除整个画布

清除上一个路径结构,并在自定义视图上调用invalidate()

mDrawings.clear();
customView.invalidate();