Реализация ластика в приложении для рисования Android - черный след, а затем прозрачный
У меня есть приложение для рисования для Android, и в настоящее время я пытаюсь добавить к нему настоящий ластик. Раньше я только что использовал белую краску для ластика, но это больше не будет, поскольку теперь я допускаю цвет фона и изображения. Я делаю это, имея изображение под моим прозрачным холстом.
Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я включаю свой ластик, он рисует сплошной черный след, пока я падаю пальцем, но как только я отпущу его, он станет прозрачным. Смотрите снимок экрана ниже:
Вот как это выглядит, когда мой палец находится на экране - сплошной черный след
![How it looks while my finger is still on the screen]()
Вот как это выглядит, как только я удаляю палец с экрана
![How it looks once I let go]()
Итак, похоже, что я приближаюсь, но я не могу найти правильную комбинацию настроек, чтобы избежать черной тропы, пока мой палец касается при стирании. Вот некоторые соответствующие фрагменты кода:
OnDraw
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(mPreviewPath, mPaint);
}
onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(currentX, currentY);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(currentX, currentY);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp(currentX, currentY);
invalidate();
break;
}
return true;
}
Текущая попытка настройки ластика
public void startEraser() {
mPaint.setAlpha(0);
mColor = Color.TRANSPARENT;
mPaint.setColor(Color.TRANSPARENT);
mPaint.setStrokeWidth(mBrushSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setMaskFilter(null);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaint.setAntiAlias(true);
}
Есть несколько других сообщений о ластиках, но большинство из них просто говорят, что используют PorterDuff.Mode.CLEAR
, setMakFilter(null)
и это должно работать. В моем случае это не так. Независимо от того, что я пытаюсь, я сначала получаю черный след, а затем желаемый результат только после того, как я выпущу.
Я могу предоставить больше кода, если это необходимо.
Ответы
Ответ 1
Я мог бы предложить вам прочитать официальный образец FingerPaint.java
Это точно соответствует тому, чего вы пытаетесь достичь здесь.
Чтобы не показывать след при удалении содержимого, посмотрите на метод onDraw()
и переменную eraserMode
:
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (!eraserMode) {
canvas.drawPath(mPath, mPaint);
}
}
boolean eraserMode = false;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
eraserMode = false;
mPaint.setXfermode(null);
mPaint.setAlpha(0xFF);
switch (item.getItemId()) {
/*...*/
case ERASE_MENU_ID:
// Add this line
eraserMode = true;
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
return true;
/*...*/
}
return super.onOptionsItemSelected(item);
}
Ответ 2
Люди Все еще ищут более короткий способ удалить эту черную линию во время стирания. Просто добавьте setLayerType(View.LAYER_TYPE_SOFTWARE, drawPaint);
эту строку в конструктор, и вот вы идете. Ура!
Ответ 3
Можете ли вы прокомментировать строку canvas.drawPath(mPreviewPath, mPaint) и посмотреть, работает ли она:
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
//canvas.drawPath(mPreviewPath, mPaint);
}
Ответ 4
когда вы хотите сделать ластик, установите цвет живописи так же, как цвет холста, который не прозрачен в реальной жизни. в андроиде мы устанавливаем цвет набора цветов как цвет темы холста, в основном белый или черный.
mColor = Color.BLACK;
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(mBrushSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
Ответ 5
Ни один из вышеперечисленных ответов не работал корректно для меня. После некоторых хитов и испытаний, а также некоторых логик, решив его, проверьте ACTION_MOVE
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isEdited = true;
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
if(isEraser) {
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath.moveTo(touchX, touchY);
} else {
drawPath.lineTo(touchX, touchY);
}
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
и этот
public void setEraser(boolean isEraser) {
this.isEraser = isEraser;
if (isEraser) {
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
} else {
drawPaint.setXfermode(null);
}
}