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

最近准备做一个涂鸦的功能,就是利用手势在图片上绘制图片,目前对于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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值