Load bitmap into canvas and draw over it

天涯浪子 提交于 2019-12-14 00:41:47

问题


I like to make an app, something like a little paint, I have to get a bitmap, draw it on a canvas and next, draw over it (with figer)... So, I actually have this code:

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Environment;
import android.util.Log;
import android.graphics.Bitmap;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class DrawView extends View implements OnTouchListener {

    private Canvas mCanvas;
    private Path mPath;
    public Paint mPaint;
    private ArrayList<Path> paths = new ArrayList<Path>();
    private boolean start = true;

    public DrawView(Context context) {
    super(context);
    setFocusable(true);
    setFocusableInTouchMode(true);
    this.setOnTouchListener((OnTouchListener) this);
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(4);
    mPaint.setDither(true);
    mPaint.setFilterBitmap(true);
    mCanvas = new Canvas();
    mPath = new Path();
    paths.add(mPath);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {

    for (Path p : paths) {
        canvas.drawPath(p, mPaint);

    }
    if (start) {
        Bitmap bmp = BitmapFactory.decodeResource(getResources(),
                R.drawable.v01);
        canvas.drawBitmap(bmp, 0, 0, mPaint);
        start = false;
    }
}

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 = new Path();
    paths.add(mPath);
}

public boolean onTouch(View arg0, 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;
}
}

With this code I can draw over the canvas, and get the bitmap by first way... But, if I touch over, the bitmap dissapears, that's cause on each onTouch event I draw again based on the path... How can I do what I like?, I mean, get the Bitmap, and draw over it...


回答1:


Should work if you move canvas.drawBitmap() outside of the if statement. Keep the decoding there, but move the actual drawing out of it.




回答2:


I'm not really sure what's your issue here. you have to redraw the bitmap every time you run onDraw, or there will be nothing there. Have you actually noticed any performance loss there?

What you don't have to do is to decode the resource on every invalidate.

Declare your bmp as a global variable

Bitmap bmp;

Store the bitmap on your constructor:

DrawView(Context context){
  ...
  bmp = BitmapFactory.decodeResource(getResources(),
                    R.drawable.v01);
  }

and remove the if on your draw method. You don't want the if there. You MUST redraw the bitmap every time you call invalidate. But this should not cause any performance issues.

canvas.drawBitmap(bmp, 0, 0, mPaint);



回答3:


This will make your view really slow, but if you remove the if(start) statement, then your bitmap won't dissapear.

A slightly better way to do it would be to take the canvas.drawBitmap() outside the if(start) method, but that will still be slow because the bitmap is being draw each time you touch the screen.


In effect this is happening because each time onDraw() is called you are passed a blank bitmap. This means that you have to redraw everything each time onDraw is called, but because you are only setting the bitmap the first time, when on draw is called again the bitmap is not added again and so dissapears.




回答4:


Solved,I used this code to can load an image and draw over it...

DrawView.java

package com.example.com.dibuja;

import java.util.ArrayList;

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

public class DrawView extends View implements OnTouchListener {
private Canvas mCanvas;
private Path mPath;
public Paint mPaint;
private ArrayList<Path> paths = new ArrayList<Path>();
Bitmap bmp;

public DrawView(Context context) {
    super(context);
    setFocusable(true);
    setFocusableInTouchMode(true);

    this.setOnTouchListener(this);
    bmp = BitmapFactory.decodeResource(getResources(), R.drawable.v01);
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLUE);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);
    mCanvas = new Canvas();
    mPath = new Path();
    paths.add(mPath);

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bmp, 0, 0, mPaint);
    for (Path p : paths) {
        canvas.drawPath(p, mPaint);
    }
}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
Draw dw = new Draw();

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 = new Path();
    paths.add(mPath);
}

@Override
public boolean onTouch(View arg0, 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;
}
}


来源:https://stackoverflow.com/questions/16989718/load-bitmap-into-canvas-and-draw-over-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!