gpt4 book ai didi

android - 尝试为 Canvas 创建橡皮擦

转载 作者:塔克拉玛干 更新时间:2023-11-02 18:52:42 24 4
gpt4 key购买 nike

我正在创建一个使用下面的 DrawingSurfaceView 类的绘图应用程序。在那个类中,我有一个名为 eraserPaint 的 Paint,用户可以打开和关闭它。当在该油漆上时,假设删除其路径中的任何内容。但它只是画了一条黑线..

当我将 Canvas 保存为透明 png 时,橡皮擦是正确的,但在屏幕上它显示黑色..

用于在 blob 上写“Erik”的 EraserPaint 的手机屏幕截图

enter image description here

从 Canvas 中保存出 PNG enter image description here

橡皮擦看起来像这样:

eraserPaint = new Paint();
eraserPaint.setAlpha(0);
eraserPaint.setColor(Color.TRANSPARENT);
eraserPaint.setStrokeWidth(60);
eraserPaint.setStyle(Style.STROKE);
eraserPaint.setMaskFilter(null);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraserPaint.setAntiAlias(true);

全类

     public KNDrawingSurfaceView(Context c, float width, float height, KNSketchBookActivity parent) {

super(c);

myWidth = width;
myHeight = height;

mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);

_parent = parent;


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


tile = new Paint();

tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.checkerpattern);
shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
tile.setShader(shader);


mPath = new Path();
eraserPaint = new Paint();
eraserPaint.setAlpha(0x00);
eraserPaint.setColor(Color.TRANSPARENT);
eraserPaint.setStrokeWidth(60);
eraserPaint.setStyle(Style.STROKE);
//eraserPaint.setMaskFilter(null);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraserPaint.setAntiAlias(true);

mBitmapPaint = new Paint(Paint.DITHER_FLAG);



mCanvas.drawRect(0, 0, myWidth, myHeight, tile);

mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);


}

@Override
protected void onDraw(Canvas canvas) {

if (!_parent.isDrawerOpen()&&mPaint!=null) {
Log.v("onDraw:", "curent paths size:" + paths.size());

//mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//canvas.drawPath(mPath, mPaint);
for (int i=0;i< paths.size();i++) {
tempPaint = paints.get(i);
eraserPaint.setStrokeWidth(tempPaint.getStrokeWidth());
if(fills.get(i)){
tempPaint.setStyle(Style.FILL_AND_STROKE);
eraserPaint.setStyle(Style.FILL_AND_STROKE);
}else{
tempPaint.setStyle(Style.STROKE);
eraserPaint.setStyle(Style.STROKE);
}
if(erasers.get(i)){
//tempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(paths.get(i), eraserPaint);
}else{
//tempPaint.setXfermode(null);
canvas.drawPath(paths.get(i), tempPaint);
}
//canvas.drawPath(paths.get(i), tempPaint);
}
if(_parent.toggleFill.isChecked()){
mPaint.setStyle(Style.FILL_AND_STROKE);
eraserPaint.setStyle(Style.FILL_AND_STROKE);

}else{
mPaint.setStyle(Style.STROKE);
eraserPaint.setStyle(Style.STROKE);
}
if(_parent.toggleErase.isChecked()){
//mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(mPath, eraserPaint);
}else{
//mPaint.setXfermode(null);
canvas.drawPath(mPath, mPaint);
}
//canvas.drawPath(mPath, mPaint);
}
}

public void onClickUndo() {

if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
undonePaints.add(paints.remove(paints.size() - 1));
undoneFills.add(fills.remove(fills.size() - 1));
undoneErasers.add(erasers.remove(erasers.size() - 1));
clearCanvasCache();
invalidate();
} else {

}
_parent.checkButtonStates();
}

public void onClickRedo() {

if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
paints.add(undonePaints.remove(undonePaints.size() - 1));
fills.add(undoneFills.remove(undoneFills.size() - 1));
erasers.add(undoneErasers.remove(undoneErasers.size() - 1));
clearCanvasCache();
invalidate();
} else {

}
_parent.checkButtonStates();
}

public void onClickClear() {

paths.clear();
paints.clear();
fills.clear();
erasers.clear();
undoneFills.clear();
undonePaths.clear();
undonePaints.clear();
undoneErasers.clear();
clearCanvasCache();
invalidate();
_parent.checkButtonStates();
}

public void saveDrawing() {

FileOutputStream outStream = null;
String fileName = "tempTag";
try {

outStream = new FileOutputStream("/sdcard/" + fileName + ".png");

mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}

}

private float mX, mY;

private static final float TOUCH_TOLERANCE = 4;

private void touch_start(float x, float y) {

undonePaths.clear();
undonePaints.clear();
undoneFills.clear();
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
if(_parent.toggleErase.isChecked()){
mCanvas.drawPath(mPath, eraserPaint);
erasers.add(true);
paints.add(eraserPaint);
}else{
mCanvas.drawPath(mPath, mPaint);
erasers.add(false);
paints.add(mPaint);
}

// kill this so we don't double draw

paths.add(mPath);


if(_parent.toggleFill.isChecked()){
fills.add(true);
}else{
fills.add(false);
}
if(_parent.toggleErase.isChecked()){
erasers.add(true);
}else{
erasers.add(false);
}


_parent.checkButtonStates();
mPath = new Path();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if(mPaint==null &&!_parent._showingAlert){
_parent.showNoPaintAlert();
}

if (!_parent.isDrawerOpen()&&mPaint!=null) {
float x = event.getX();
float y = event.getY();
if (x > myWidth) {
x = myWidth;

}
if (y > myHeight) {
y = myHeight;

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

public void clearCanvasCache() {

mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
}

我应该补充一点,我正在将这个自定义 View 添加到一个以方格图案作为背景图像的相对布局中。

拜托拜托拜托求助..我需要预览图像在使用橡皮擦油漆后不显示黑色..我需要它来显示后面的方格图案..我知道橡皮擦正在工作,因为那些黑色橡皮擦标记保存了透明。

新笔记

我在四处游玩,发现了一些其他有趣的东西。实验中,我尝试从绘图切换到传递给 onDraw 方法的 canvas,然后直接切换到我在名为 mCanvas 的构造函数中设置的 Canvas 并注意到它没有绘制到我能看到的那么远..所以我向 onDraw 添加了一个日志,如下所示:

 protected void onDraw(Canvas canvas) {
Log.v("DRAWING SURFACE", "canvas:"+canvas+" mCanvas:"+mCanvas);

吐出来的

06-21 11:10:43.994: V/DRAWING SURFACE(4532): canvas:android.view.Surface$CompatibleCanvas@42a8c030 mCanvas:android.graphics.Canvas@431df180

最佳答案

我的应用程序也遇到了同样的问题。我什至尝试了“finger paint”示例代码,但仍然遇到同样的问题。我永远无法让橡皮擦作为路径工作,但我找到了解决方法。我不是在删除时绘制路径,而是在用户放下手指或出现“移动”事件时绘制一个圆圈(可以是任何形状):

case MotionEvent.ACTION_DOWN:
mPaint.setStrokeWidth(25);
mPaint.setXfermode(new PorterDuffXfermode(
PorterDuff.Mode.CLEAR));
mCanvas.drawCircle(x, y, 10, mPaint);
isErase = true;
invalidate();
}
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if(isErase)
{
mCanvas.drawCircle(x, y, 20, mPaint);
}
else{
touch_move(x, y);
}invalidate();
break;

将其合并到您的代码中需要一些时间,但我向您保证,这将花费比您已经花在尝试解决此问题上的时间更少的时间。如果您认为有帮助,我可以向您发送更多我的 PaintView。

关于android - 尝试为 Canvas 创建橡皮擦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17197435/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com