Drawing on Canvas and save image

痴心易碎 提交于 2019-11-27 11:09:27
Belovoj

I saw really good code on android developers, but I can't find it anymore... It's output is bezier curves so it will be pretty smooth. Here is code that I edited:

public class MyDrawView extends View {

private Bitmap  mBitmap;
private Canvas  mCanvas;
private Path    mPath;
private Paint   mBitmapPaint;
private Paint   mPaint;

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

    mPath = new Path();
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0xFF000000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(3);
}

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

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

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

public void clear(){
    mBitmap.eraseColor(Color.TRANSPARENT);
    invalidate();
    System.gc();
}}

then in onCreate of activity you want to use it in you just write something like this:

RelativeLayout parent = (RelativeLayout) findViewById(R.id.signImageParent);
myDrawView = new MyDrawView(this);
parent.addView(myDrawView);

This view is transparent and uses black paint to draw with your finger. So if you want see what you draw simply draw a white or gray bitmap on background of this view (you just add one line in the beginnig of onDraw), or you can use the background of the parent.

Then when you want to create an image from what you have drawn you just call

parent.setDrawingCacheEnabled(true);
Bitmap b = parent.getDrawingCache();

FileOutputStream fos = null;
try {
fos = new FileOutputStream(getFileName());
} catch (FileNotFoundException e) {
e.printStackTrace();
}

b.compress(CompressFormat.PNG, 95, fos);

It depends on what you want to have as output, you can use this code or instead of parent you can do this with myDrawView and you get just the image you have drawn without background (since we have our myDrawView background transparent).

Hope this will help. Feel free to leave feedback.

the drawing thing

Scribbler.java:

package org.yourpackage.scribble;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;

public class Scribbler extends Activity {
    DrawView drawView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        drawView = new DrawView(this);
        drawView.setBackgroundColor(Color.WHITE);
        setContentView(drawView);
        drawView.requestFocus();

    }
}

DrawView.java:

package org.yourpackage.scribble;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class DrawView extends View implements OnTouchListener {
    List<Point> points = new ArrayList<Point>();
    Paint paint = new Paint();

    public DrawView(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setOnTouchListener(this);
        paint.setColor(Color.BLACK);
    }

    @Override
    public void onDraw(Canvas canvas) {
        for (Point point : points) {
            canvas.drawCircle(point.x, point.y, 2, paint);  
        }
    }

    public boolean onTouch(View view, MotionEvent event) {
        Point point = new Point();
        point.x = event.getX();
        point.y = event.getY();
        points.add(point);
        invalidate();
        return true;
    }
}

class Point {
    float x, y;
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.yourpackage.scribble"
      android:versionCode="1"
      android:versionName="1.0">
    <application>
        <activity android:name=".Scribbler">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest> 

..will give you something like that:

You may want to draw lines instead of pixels

the saving thing

To implement saving you can pass a Bitmap into the Canvas constructor, then use the compress method of Bitmap to create an OutputStream which can be written to the SD card

EDIT to answer your comment:
Sure you can use XML to define your layout since DrawView extends View you can use it in your layout xml file. An example for the main.xml layout file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/linearLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/gradient"
    >

    <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
    <org.yourpackage.scribble.DrawView android:id="@+id/drawView1" android:layout_width="wrap_content" android:layout_height="wrap_content">        </at.gru.android.drawdemo.DrawView>
</LinearLayout>

that gives you something like that:


You'll just need an additional contstructor public DrawView(Context context, AttributeSet attrSet)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!