Android canvas 重叠图像

Android canvas overlaying image

我正在尝试将图像添加到 android canvas 并且能够用手指绘画来注释图像。我已经修改了 from this tutorial at tuts plus

我可以从我的 drawables 文件夹中对图像进行硬编码并在上述 image.My 上面绘画 现在的问题是 canvas 覆盖在我的图像之上,超出了图像本身。这个想法是能够注释图像并在图像边界之外做笔记。

这是我的笔操作的截图

这里我在尝试了几次笔操作后得到了渲染输出。

这是我的代码。我为附上整个东西而道歉,我在 androids 是一个极端的 n00b,所以我不确定要附上什么。我试图隔离我的操作,仅在我调用 'startNew()' 方法时调用,该方法在我点击 FAB 按钮上的加号图标时调用。在没有图像的原始 canvas 中,笔渲染并保留在整个白色 space 上。我保留了 Log.i 条消息,以便在控制台中查看何时调用了哪些方法以获得一些自我意识。

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;


public class DrawingView extends ViewGroup {

//drawing path
private Path drawPath;
//ImageView choosenImageView;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
private Bitmap bmp;
private Bitmap mutableBitmap;
private Bitmap newBitmap;
private float brushSize, lastBrushSize;
private boolean erase=false;
private boolean theCanvas=false;



private void setUpDrawing(){
    Resources res = getResources();
    Log.i("SETUP","OMG SO MUCH SETUP");
    brushSize = getResources().getInteger(R.integer.medium_size);
    lastBrushSize = brushSize;
    drawPath = new Path();
    drawPaint = new Paint();
    drawPaint.setColor(paintColor);
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(brushSize);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    canvasPaint = new Paint(Paint.DITHER_FLAG);
}
public void startNew(){
    Log.i("NEW","SO NEWW");
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    Resources res=getResources();
    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inScaled=false;
    bmpFactoryOptions.inJustDecodeBounds = false;
    bmp = BitmapFactory.decodeResource(res, R.drawable.jupiter, bmpFactoryOptions);
    mutableBitmap=bmp.copy(Bitmap.Config.ARGB_8888, true);
    drawCanvas.drawBitmap(mutableBitmap,0,0,drawPaint);
    canvasBitmap=mutableBitmap;
    theCanvas=true;
    drawCanvas = new Canvas(canvasBitmap);
    invalidate();
}
public void putOverlay(Bitmap bitmap, Bitmap overlay) {
    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
    canvas.drawBitmap(overlay, 0, 0, paint);
}
public void setErase(boolean isErase){
//set erase true or false
    erase=isErase;
    if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    else drawPaint.setXfermode(null);
}
public void setBrushSize(float newSize){
//update size
    float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
            newSize, getResources().getDisplayMetrics());
    brushSize=pixelAmount;
    drawPaint.setStrokeWidth(brushSize);
}

public void setLastBrushSize(float lastSize){
    lastBrushSize=lastSize;
}
public float getLastBrushSize(){
    return lastBrushSize;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
    super.onSizeChanged(w, h, oldw, oldh);
    Log.i("SIZEE", "THE ISZEE IS CHANGES");
    bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mutableBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

@Override
protected void onDraw(Canvas canvas) {
//draw view
    if(theCanvas){
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
        }else {
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
        }
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    final int count = getChildCount();
    Log.i("onlayout","hello shouldn't come heres");
}



@Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch

    float touchX = event.getX();
    float touchY = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i("onDown","hello onpen DOWN");
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            //Log.i("onMOVINGS","hello ondraw");
            drawPath.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            Log.i("line","drew some shitty line");
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}

public void setColor(String newColor){
//set color
    invalidate();
    paintColor = Color.parseColor(newColor);
    drawPaint.setColor(paintColor);


}
public DrawingView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setUpDrawing();
    Log.i("someshintg","context1");

}

public DrawingView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    Log.i("someshintg","context2");

}
public DrawingView(Context context) {
    super(context);
    Log.i("someshintg","context3");
}
}

更新:

public void startNew(){
    Log.i("NEW","SO NEWW");
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    Resources res=getResources();
    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inScaled=false;
    bmpFactoryOptions.inJustDecodeBounds = false;
    bmp = BitmapFactory.decodeResource(res, R.drawable.jupiter, bmpFactoryOptions);
    mutableBitmap=bmp.copy(Bitmap.Config.ARGB_8888, true);
    drawCanvas.drawBitmap(mutableBitmap,0,0,drawPaint);
    //canvasBitmap=mutableBitmap;
    theCanvas=true;
    //drawCanvas = new Canvas(canvasBitmap);
    invalidate();
}

我编辑了我的代码,尽量不修改 drawCanvas 对象,只是让可变位图成为与图像本身关联的位图。结果是图像占用了太多 space,我认为这很奇怪,因为我使用 inScaled=false; 使其与之前的父对象不匹配。我曾尝试在我的 XML 布局中使用 ImageView 占位符,但我无法让它们在 canvas 本身中呈现; imageView 在 canvas 下呈现为同级,但当作为 canvas 的子级放置时,它是不可见的。这是当前代码实现的屏幕截图:

您检查过 canvas 的尺寸了吗? 对我来说,看起来 canvas 大小设置为位图大小,因此绘制的注释仅在位图中可见

我能够通过使用 canvas drawBitmap 来解决这个问题,它获取源和目标矩形(对此仍然不确定)并将其设置为我想要显示的矩形。

声明了 private Rect imgRect;

onSizeChanged 在应用程序首次打开时调用,并且提供给 onSizeChanged 的​​参数是屏幕宽度和高度,所以我也用它来获取要在 startNew 中使用的尺寸

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
    super.onSizeChanged(w, h, oldw, oldh);
    Log.i("SIZEE", "THE ISZEE IS CHANGES");
    imgRect = new Rect(0,0,w*2,h*2);
    bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mutableBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

public void startNew(){
    Log.i("NEW","SO NEWW");
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    Resources res=getResources();
    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inScaled=false;
    bmpFactoryOptions.inJustDecodeBounds = false;
    bmp = BitmapFactory.decodeResource(res, R.drawable.jupiter, bmpFactoryOptions);
    mutableBitmap=bmp.copy(Bitmap.Config.ARGB_8888, true);
    drawCanvas.drawBitmap(mutableBitmap,imgRect,imgRect,drawPaint);
    //canvasBitmap=mutableBitmap;
    theCanvas=true;
    invalidate();
}