在SurfaceView/自定义View中利用手势绘制不同颜色不同形状的图形并且保存为Bitmap位图

来源:互联网 发布:java清除cookie 编辑:程序博客网 时间:2024/05/21 12:42

最近准备做一个涂鸦的功能,就是利用手势在图片上绘制图片,目前对于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也保持同步绘制

//先绘制上次绘制的bitmapcanvas.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);    }}
阅读全文
0 0