android - 保存 Canvas 以供将来使用

标签 android android-canvas

我有一个从 EditText 扩展的 View ,它允许用户编写文本,然后在同一 View 中用手指绘图。

我想要的是保存该项目以供将来使用,我正在考虑当应用程序被销毁然后打开时,抽奖将被删除。我想要的是一种在用户下次打开应用程序时保存此绘图的方法。

对于文本,我使用了 sharedPreferences 将文本保存在 onPause 中,而对于绘制,我不知道如何保存。

我认为将绘图另存为图像文件不是保存它的方法,但我不知道。

编辑:

我尝试将位图保存为 jpeg,然后绘制到 Canvas 上。但它不起作用,最后它以黑色显示对象并且不允许我绘制。

我的代码如下,最后写了我创建的两个方法,但它们效果不佳。它们是 saveBitmap()openBitmap():

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import android.content.Context;
import android.graphics.*;
import android.os.Environment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.EditText;

public class DrawEditText extends EditText {

    private Bitmap  mBitmap;
    private Canvas  mCanvas;
    private Path    mPath;
    private Paint   mBitmapPaint;
    private Paint   mPaint;
    private MaskFilter  mEmboss;
    private MaskFilter  mBlur;
    private int brush;        
    private Boolean drawing;
    private int maxLines;

    public DrawEditText(Context c) {
        super(c);


        //This initializes all the objects
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
        mBitmapPaint.setColor(Color.TRANSPARENT);

        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setAntiAlias(true);

        mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
                0.4f, 6, 3.5f);

        mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);

        drawing = false;
        brush = -1;
        maxLines = 20;
    }
    public DrawEditText(Context c, AttributeSet attrs) {
        super(c, attrs);

        //This initializes all the objects
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);

        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setAntiAlias(true);

        mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
                0.4f, 6, 3.5f);

        mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);

        drawing = false;
        brush = -1;
        maxLines = 20;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);
        super.onDraw(canvas);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        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);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

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

        //This conditional makes that if not it's drawing no points are saved and no points are drawed
        if (drawing){
            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;
        } else {
            return super.onTouchEvent(event);
        }
    }

    public void changePaint(int stroke, int color){
        mPaint.setColor(color);
        mPaint.setStrokeWidth(stroke);
    }
    public void clear(){
        mCanvas.drawColor(0x00AAAAAA);
        mCanvas.drawColor( 0, PorterDuff.Mode.CLEAR );
        setText("");
    }
    public void changeBrush(int id){
        //String[] ids={"emboss", "blur", "another"};
        switch (id) {
        case 0:
            mPaint.setMaskFilter(mEmboss);
            brush = 0;
            break;
        case 1:
            mPaint.setMaskFilter(mBlur);
            brush = 1;
            break;
        case 2:
            mPaint.setMaskFilter(null); 
            brush = -1;
            break;
        default:
            mPaint.setMaskFilter(null);
            brush = -1;
            break;
        }
    }
    public int getBrush(){
        //String[] ids={"emboss", "blur", "another"};
        return brush;
    }
    public void eraser(){
        mPaint.setMaskFilter(null); 
        mPaint.setColor(0x00AAAAAA);
    }

    public void setDrawing(Boolean drawing){
        this.drawing = drawing;
    }

    public Boolean isDrawing(){
        return drawing;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        TextWatcher watcher = new TextWatcher() {

            private String text;
            private int beforeCursorPosition = 0;

            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
                text = s.toString();
                beforeCursorPosition = start;
            }

            @Override
            public void afterTextChanged(Editable s) {

                /* turning off listener */
                removeTextChangedListener(this);

                /* handling lines limit exceed */
                if (DrawEditText.this.getLineCount() > maxLines) {
                    DrawEditText.this.setText(text);
                    DrawEditText.this.setSelection(beforeCursorPosition);
                }

                /* turning on listener */
                addTextChangedListener(this);

            }
        };

        this.addTextChangedListener(watcher);
    }

    @Override
    public int getMaxLines() {
        return maxLines;
    }

    @Override
    public void setMaxLines(int maxLines) {
        this.maxLines = maxLines;
    }

    public void saveBitmap(){
        mCanvas.setBitmap(mBitmap);
        File sd = Environment.getExternalStorageDirectory();
        File myDir = new File(sd + "/tweeet");    
        myDir.mkdirs();
        File f = new File(myDir, ".drawing.jpeg");
        try {
            if (myDir.canWrite()) {
                 f.createNewFile();
                 OutputStream os = new FileOutputStream(f);
                 mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
                 os.close();
            }
       } catch (FileNotFoundException e) {
            e.printStackTrace();
       } catch (IOException e) {
            e.printStackTrace();
       }
    }
    public void openBitmap(){
        File sd = Environment.getExternalStorageDirectory();
        File myDir = new File(sd + "/tweeet");    
        myDir.mkdirs();
        File f = new File(myDir, ".drawing.jpeg");
        mBitmap = BitmapFactory.decodeFile(f.getPath());
    }
}

最佳答案

  1. 将图像从 Canvas 保存到文件。 Here is how to do it.
  2. onResume() 中加载图像文件并将其绘制在 Canvas 上。

关于android - 保存 Canvas 以供将来使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19477961/

相关文章:

Android - 如何循环缩放/放大图像的一部分?

android - 手绘图像裁剪在位图区域内绘制

java - Android SQLite 查询顺序问题

android - AsyncTask.onPostExecute() 的参数与实例变量

android - 从 Assets 文件夹中检索图像路径

android - 屏幕旋转 fragment

使用 Canvas 的 Android 弹跳球

Android TV 运营商等级

android - 在 ImageView 上移动形状?

Android 剪辑 canvas.drawBitmap