Андроидный холст удалить предыдущий путь
Я создаю приложение для рисования и хочу реализовать функцию отмены, чтобы удалить предыдущий обратный путь.
Coding:
private HashMap<Integer, Path> pathMap; // current Paths being drawn
private HashMap<Integer, Point> previousPointMap; // current Points
private Bitmap bitmap; // drawing area for display or saving
private Canvas bitmapCanvas; // used to draw on bitmap
private Paint paintScreen; // use to draw bitmap onto screen
private Paint paintLine; // used to draw lines onto bitmap
public DrawView(Context context, AttributeSet attrs)
{
super(context, attrs); // pass context to View constructor
this.context_new=context;
paintScreen = new Paint(); // used to display bitmap onto screen
// set the initial display settings for the painted line
paintLine = new Paint();
paintLine.setAntiAlias(true); // smooth edges of drawn line
paintLine.setColor(Color.BLACK); // default color is black
paintLine.setStyle(Paint.Style.STROKE); // solid line
paintLine.setStrokeWidth(5); // set the default line width
paintLine.setStrokeCap(Paint.Cap.ROUND); // rounded line ends
pathMap = new HashMap<Integer, Path>();
previousPointMap = new HashMap<Integer, Point>();
} // end DrawView constructor
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(bitmap, 0, 0, paintScreen);
for (Integer key : pathMap.keySet())
canvas.drawPath(pathMap.get(key), paintLine);
}
// called when the user finishes a touch
private void touchEnded(int lineID)
{
Path path = pathMap.get(lineID); // get the corresponding Path
bitmapCanvas.drawPath(path, paintLine); // draw to bitmapCanvas
path.reset(); // reset the Path
rememberLineId = lineID;
} // end method touch_ended
//undo
private void undo()
{
Path path = pathMap.get(rememberLineId); // get the corresponding Path
pathMap.remove(rememberLineId);
bitmapCanvas.clearPath(path, paintLine);
path.reset(); // reset the Path
}
Вопрос:
Однако, похоже, что этот метод отсутствует bitmapCanvas.clearPath
? Если тогда, как это можно изменить?
Изменены коды:
Объявления:
private Bitmap bitmap; // drawing area for display or saving
private Canvas bitmapCanvas; // used to draw on bitmap
private Paint paintScreen; // use to draw bitmap onto screen
private Paint paintLine; // used to draw lines onto bitmap
private HashMap<Integer, Path> pathMap; // current Paths being drawn
private HashMap<Integer, Point> previousPointMap; // current Points
private Bitmap bitmapBackup;
OnSizeChanged
@Override
public void onSizeChanged(int w, int h, int oldW, int oldH)
{
super.onSizeChanged(w, h, oldW, oldH);
DoodlzViewWidth = w;
DoodlzViewHeight = h;
bitmapBackup = Bitmap.createBitmap(getWidth(), DoodlzViewHeight, Bitmap.Config.ARGB_8888);
bitmap = Bitmap.createBitmap(getWidth(), DoodlzViewHeight, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
bitmap .eraseColor(Color.WHITE); // erase the BitMap with white
bitmapBackup.eraseColor(Color.WHITE);
}
Метод FirsttoBackup будет вызываться, если ниже работает TouchedStart
public void firsttobackup()
{
bitmapBackup=bitmap;
Toast message = Toast.makeText(getContext(), "backuped 123", Toast.LENGTH_SHORT);
message.show(); //THIS TOAST CAN BE SUCESSFULLY PRESENTED when touching screen starting to draw
}
OnDraw
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(bitmap, 0, 0, paintScreen);
for (Integer key : pathMap.keySet())
canvas.drawPath(pathMap.get(key), paintLine);
}
OnTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getActionMasked(); // event type
int actionIndex = event.getActionIndex(); // pointer (i.e., finger)
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN)
{
firsttobackup(); //TOAST CAN SHOW "BACKUP 123"
touchStarted(event.getX(actionIndex), event.getY(actionIndex),
event.getPointerId(actionIndex));
}
Отменить: пользователь, нажавший кнопку отмены, вызовет этот
public void undo()
{
bitmap = bitmapBackup.copy(Bitmap.Config.ARGB_8888, true);
bitmapCanvas = new Canvas(bitmap);
}
Пересмотренный вопрос:
Теперь используется метод firsttobackup()
, так что bitmapBackup установил = bitmap при выполнении OnTouchEvent
touchStarted
. Я вложил в него тост, и вам нужно будет представить "резервную копию 123", когда пользователь нажимает на экран и начинает рисовать.
Когда пользователь нажимает кнопку отмены, он будет вызывать метод undo
, но теперь, нажав кнопку отмены, никаких действий не видно... почему?
Спасибо!!
Ответы
Ответ 1
Я думаю, что самый простой способ сделать это - иметь 2 растровых изображения (1 дополнительный бит файл для восстановления предыдущего состояния).
Перед тем, как начинать новые чертежи, вам нужно сохранить предыдущее состояние растрового изображения.
Вот как я бы изменил ваш код:
private HashMap<Integer, Path> pathMap; // current Paths being drawn
private HashMap<Integer, Point> previousPointMap; // current Points
private Bitmap bitmap; // drawing area for display or saving
private Bitmap bitmapBackup;
private Canvas bitmapCanvas; // used to draw on bitmap
private Canvas bitmapBackupCanvas;
// remember last bitmap before new drawings...
private void touchStarted()
{
bitmapBackupCanvas.drawBitmap(bitmap, 0, 0, null);
}
// called when the user finishes a touch
private void touchEnded(int lineID)
{
Path path = pathMap.get(lineID); // get the corresponding Path
bitmapCanvas.drawPath(path, paintLine); // draw to bitmapCanvas
path.reset(); // reset the Path
rememberLineId = lineID;
} // end method touch_ended
//undo
private void undo()
{
Path path = pathMap.get(rememberLineId); // get the corresponding Path
pathMap.remove(rememberLineId);
bitmapCanvas.drawBitmap(bitmapBackup, 0, 0, null); // restore from backup
path.reset(); // reset the Path
}
Ответ 2
Это старый пост, но я тоже искал ответ на этот вопрос. Я не был удовлетворен выбранным ответом для этого поста, и сам нашел его после этого. Я на самом деле думаю, что наличие полной битовой карты в качестве резервной копии не очень хорошо с точки зрения памяти, и это ограничит количество шагов отмены, которые мы можем сделать.
Я считаю, что лучшим решением будет:
Иметь стек путей в вашем классе
private Stack<Path> m_pathHistory = new Stack<Path>();
рядом с вашим холстом:
private Canvas m_drawingCanvas;
Затем каждый раз, когда обводка завершается (при событии подкраски), добавляется "клон" пути в историю отмен:
m_pathHistory.Push(new Path(currentPath));
И здесь функция отмены:
public void Undo()
{
if(m_pathHistory.Count > 0)
{
m_pathHistory.Pop(); // Remove the last path from the history
m_drawingCanvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear); // Clear the canvas with a transparent color
// Draw the paths which are still in the history
foreach (Path p in m_pathHistory)
{
m_drawingCanvas.DrawPath(p, m_paint);
}
}
}
Пути гораздо меньше для хранения в памяти, чем полные растровые изображения, поэтому у нас может быть гораздо большая история.
Ответ 3
см. здесь, можно использовать полный этот способ рисования и прозрачной краски
http://polamreddyn.blogspot.in/2012/11/simple-free-hand-paint-with-color.html
и этот
http://polamreddyn.blogspot.in/2012/10/free-hand-graw.html
Ответ 4
На первый взгляд я вижу следующие проблемы:
Добавив пустой Path
в paths
, как только вы его сделаете, вы у вас будет проблема, как только вы отмените: вы выскользнете из этого пустого Path
во-первых, сделать первый откат, похоже, не работает. Тогда, если вы нарисуете в этот Path
он не добавляется к paths
. Решение состоит в том, чтобы добавить завершена Path
до путей в touch_up()
перед созданием нового.
То есть, удалите
paths.add(mPath);
из конструктора, а в touch_up()
измените
mPath = new Path();
paths.add(mPath);
к
paths.add(mPath);
mPath = new Path();
Вы также захотите добавить
canvas.drawPath(mPath, mPaint);
после цикла for
в onDraw()
, чтобы нарисовать прогресс Path
.
Вы не опорожняете undonePaths
, когда пользователь снова начнет рисовать.
Ответ 5
если вы используете PorterDuffXfermode
, сохраните представление в своем bitmapBackup
,
вместо предыдущего растрового изображения
public void undo (){
bitmap.eraseColor(getDrawingCacheBackgroundColor());
mCanvas.drawBitmap(bitmapBackup, 0, 0, null);
invalidate();
mPath.reset();
undofresh=true;
}
private void touch_start(float x, float y) {
View v1 = this;
v1.setDrawingCacheEnabled(true);
this.bitmapBackup = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
}
Ответ 6
use path.reset()in the MotionEvent.ACTION_DOWN event of OnTouchEvent() method.
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.reset();
invalidate();
break;
}
return true;
}