我正在制作一个绘图应用,并希望实现一个撤消功能来删除之前的绘制路径。
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's 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在执行OnTouchEvent
touchStarted
时设置=位图。我已经在其中放了一个吐司,当用户按下屏幕并开始绘制时,可以提供“备份123”。
当用户点击撤销按钮时,它将调用undo
方法,但现在按下撤消按钮,无法看到任何操作......为什么?
谢谢!
答案 0 :(得分:8)
我认为最简单的方法是使用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
}
答案 1 :(得分:4)
这是一篇旧文章,但我也在寻找该问题的答案。我对为该帖子选择的答案不满意,此后我自己找到了一个。 实际上,我认为拥有完整的位图作为备份并不是一个很好的内存管理方法,它将限制我们可以执行的撤消步骤。
我相信更好的解决方案是:
要在课程中添加一堆路径
private Stack<Path> m_pathHistory = new Stack<Path>();
画布和画笔旁边(跳过初始化):
private Canvas m_drawingCanvas;
private Paint m_paint;
然后,每完成一次笔画(在修饰事件中),在撤消历史记录中添加路径的“克隆”:
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);
}
}
}
要存储在内存中的路径比完整的位图要小得多,因此我们可以拥有更大的历史记录。
答案 2 :(得分:1)
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;
}
答案 3 :(得分:0)
http://polamreddyn.blogspot.in/2012/11/simple-free-hand-paint-with-color.html
和这个
答案 4 :(得分:0)
乍一看,我发现以下问题:
将
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
。
当用户再次开始绘图时,您不会清空{{1}}。
答案 5 :(得分:0)
如果您使用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);
}