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

Java 保存新图像时,会保留旧画布,java,android,android-canvas,Java,Android,Android Canvas,我有一个画布,允许用户绘制和保存。它还允许用户更改颜色,并使用不同的颜色在同一画布上绘制 我的绘画课: 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.

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

我的绘画课:

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;
    }
}
在我的活动中,我调用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);
         }
     }
}
我希望做的是:

当我画一些东西并保存图像时,共享按钮应该出现,画布不应该清除 当“共享”按钮可见时,我在画布上绘制了其他内容,“保存”按钮应重新出现 当我再次按下SAVE按钮时,它应该会保存新的画布图形,但不工作,它正在保存我在第一步中保存的先前绘制的画布 如何修改代码以执行此操作:

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

每次用户触摸画布并理论上绘制一些东西时,为其创建路径。存储新路径及其颜色,并在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;
如果按下擦除按钮,则清除整个画布

清除以前的路径结构并在自定义视图上调用invalidate:

mDrawings.clear();
customView.invalidate();
不要为每种颜色创建新画布,而是创建新路径

每次用户触摸画布并理论上绘制一些东西时,为其创建路径。存储新路径及其颜色,并在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;
如果按下擦除按钮,则清除整个画布

清除以前的路径结构并在自定义视图上调用invalidate:

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

我不能在Paint类中使用私有变量,因为我将从另一个类访问这些变量。正在初始化的变量密钥在哪里?@ZahidH private关键字不起作用,如果需要可以删除它。关于输入错误的关键变量,它是前一行的颜色//使用下面的路径。我的代码里的其他东西都应该是对的吗?@ZahidH我不知道我应该看到什么?!您应该尝试并测试代码,然后提及出现的任何问题。@ZahidH如果您想要绘制路径的确切顺序,则需要一种新的方法。我对我的答案做了一些修改。我不理解save的问题。我不能在我的Paint类中使用私有变量,因为我将从另一个类访问这些变量。正在初始化的变量密钥在哪里?@ZahidH private关键字不起作用,如果需要可以删除它。关于输入错误的关键变量,它是前一行的颜色//使用下面的路径。我的代码里的其他东西都应该是对的吗?@ZahidH我不知道我应该看到什么?!您应该尝试并测试代码,然后提及出现的任何问题。@ZahidH如果您想要绘制路径的确切顺序,则需要一种新的方法。我对我的答案做了一些修改。我不明白储蓄的问题。