Drawing on Canvas and save image

前端 未结 2 1514
误落风尘
误落风尘 2020-12-04 11:25

I am new to the Android Graphics class. I want to draw an image(actually a signature kind) using the touch events and want it to be saved on SDcard when I want to save it. I

相关标签:
2条回答
  • 2020-12-04 12:04

    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:

    alt text

    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:
    enter image description here
    You'll just need an additional contstructor public DrawView(Context context, AttributeSet attrSet)

    0 讨论(0)
  • 2020-12-04 12:12

    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.

    0 讨论(0)
提交回复
热议问题