最近准备做一个涂鸦的功能,就是利用手势在图片上绘制图片,目前对于APP开发还是比较火的,最近刚好项目需要就自己准备研究研究了。
一开始的第一感觉我就是用的自定义View,利用onDraw中的Canves根据手势来进行绘制,后来查阅了网上的资料说利用自定义SurfaceView的效率会更高点,因此,自己就尝试利用自定义SurfaceView来研究研究。因为时间原因我就不详细的描述了,我主要描述一下问题解决的思路吧,望各位同道中人可以理解。哈哈~(后面贴上源码^-^)
1、`public class PaletteView extends SurfaceView`,首先这个我就不多说了哈。
2、其次,对于新手来说如何在surfaceView中绘制就有点丈二的和尚摸不着头脑了(其实我就是),就是利用mHolder=getHolder();然后通过Canvas canvas = mHolder.lockCanvas(null);来获取Canves绘图的画布,接下来你就可以在Canves中开始绘图了.(注意:这一切都要先实现mHolder.addCallback(this);这个回调,然后在接口的实现方法public void surfaceCreated(SurfaceHolder arg0)中开始初始化)。
3、对于绝大数人来说实现一个根据手势绘图都没有什么问题的,但是实现这个涂鸦思路就卡在如何利用不同颜色的笔,不同粗细的笔进行绘制,原来绘制的东西还在上面。我们都知道,不管是自定义View还是自定义Surface View里面一个重要的绘制机制就是在自定义View中的onDraw每次在刷新的时候都会清空Canves画布,(这个我也纠结了好长时间),一直都无法在原先的图画上绘制新的图形。其实解决这样的问题的重要的思路就是先定义一个自己的canves
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.se17_bg).copy(Bitmap.Config.ARGB_8888, true);
mCanvas = new Canvas(mBitmap);
当然,此mCanvas和Canvas canvas = mHolder.lockCanvas(null);不一样,我们的重要的思路就是保存自定义的mCanvas画布和surfaceView的canves保持同步绘制,我们都知道,如果在将canves转成bitmap就必须要mCanvas = new Canvas(mBitmap);当在mCanves中绘制时,bitmap也保持同步绘制。这样我们解决起来就容易多了。
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsDrawing=true;
mPath=new Path();
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
draw();
break;
case MotionEvent.ACTION_UP:
mIsDrawing=false;
break;
default:
break;
}
return true;
}
每当draw()绘制的时候,先将上次绘制的bitmap回到的surfaceView的canves中,然后再绘制,同时自定义的mCanves也保持同步绘制
//先绘制上次绘制的bitmap
canvas.drawBitmap(mBitmap,0,0,null);
//再绘制手势的路径
canvas.drawPath(mPath, mPaint);
//保持同步绘制
mCanvas.drawPath(mPath, mPaint);
这样就ok了,其实问题就在这些地方,方法不难,就是这样的思路想起来有点难。也许我表达上有点难懂(都是程序猿,大家都懂的!!!!!),接下来我就贴上Dome的源码:
public class PaletteView extends SurfaceView implements SurfaceHolder.Callback {
/**
* 是否处于绘制状态
*/
private boolean mIsDrawing;
/**
* 帮助类
*/
private SurfaceHolder mHolder;
/**
* 画布
*/
private Canvas mCanvas;
/**
* 路径
*/
private Path mPath;
/**
* 画笔
*/
private Paint mPaint;
/**
* 屏幕的宽度
*/
private int screenWidth;
/**
* 屏幕的高度
*/
private int screenHeight;
/**
* 图片Bitmap
*/
private Bitmap mBitmap;
private boolean isFirst = true;
private int mPaintColor = Color.GREEN;
public PaletteView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
public PaletteView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public PaletteView(Context context) {
super(context);
initView(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsDrawing=true;
//新建路径
mPath=new Path();
//移动到起始位置
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
//绘制路径
mPath.lineTo(x, y);
//绘制路径到views上
draw();
break;
case MotionEvent.ACTION_UP:
mIsDrawing=false;
break;
default:
break;
}
return true;
}
private void initView(Context context) {
mHolder=getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPath=new Path();
mPaint=new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mPaintColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(15);
//获取屏幕的宽高
Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
screenHeight = display.getHeight();
screenWidth = display.getWidth();
//生成自己的bitmap和mCanves
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.se17_bg).copy(Bitmap.Config.ARGB_8888, true);
mCanvas = new Canvas(mBitmap);
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
mIsDrawing=true;
//初始化白色画布
draw();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
mIsDrawing=false;
}
private void draw(){
Canvas canvas=mHolder.lockCanvas(null);
try {
canvas.drawColor(Color.WHITE);
//先绘制上次绘制的bitmap
canvas.drawBitmap(mBitmap,0,0,null);
//再绘制手势的路径
canvas.drawPath(mPath, mPaint);
//保持同步绘制
mCanvas.drawPath(mPath, mPaint);
if (isFirst){
mIsDrawing = false;
isFirst = false;
}
} catch (Exception e) {
e.printStackTrace();
} finally{
if (canvas!=null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
/**
* 获取当前绘制的Bitmap
* @return
*/
public Bitmap getCanvesBitmap(){
return mBitmap;
}
public void setmPaintColor(int mPaintColor) {
this.mPaintColor = mPaintColor;
mPaint.setColor(mPaintColor);
}
}