清明节做了个画板App

说明:实现了绘画、橡皮擦、嵌入图片、更改颜色、回退,图片分享、保存、预览等功能

0.截图如下

图1 字体
图2 颜色
图3 嵌入图片
图4 大师成品

1.绘画

  • 自定义绘制 PaintSurfaceView 继承 SurfaceView实现SurfaceHolder.Callback, Runnable接口 在子线程完成
//初始化画笔
	private void init() {
        mHolder = getHolder();
        mHolder.addCallback(this);

        sizeBrush = sizeEraser = 12;
        colorBackground = Color.WHITE;
        mPaint.setColor(Color.BLACK);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(toPx(sizeBrush));

        rotateImage = Utils.getBitmapFromDrawable(getContext(), R.drawable.ic_rotate_right_black_24dp);
        captureImage = Utils.getBitmapFromDrawable(getContext(), R.drawable.capture);
        //非vector图片直接解析
        //captureImage = BitmapFactory.decodeResource(getResources(), R.drawable.capture);
    }


 @Override
    public void surfaceCreated(SurfaceHolder holder) {
        this.mHolder = holder;
        if (drawThread != null) {
            drawingActive = false;
            try {
                drawThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        surfaceReady = true;
        startDrawThread();
   	 }


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        if (w == 0 || h == 0) {
            return;
        }
        bitmapBackground = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        //画布色
        bitmapView = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        //初始化画布
        mCanvas = new Canvas(bitmapView);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopDrawThread();
        holder.getSurface().release();
        this.mHolder = null;
        surfaceReady = false;
    }

2.橡皮擦


    /**
     * 橡皮擦可用
     */
    public void setEnableEraser() {
        //着色的一个模式
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    }

    /**
     * 橡皮擦不可用
     */
    public void disableEraser() {
        mPaint.setXfermode(null);
        //着色器 在学习openGl es的时候很常用
        mPaint.setShader(null);
        //蒙版滤镜
        mPaint.setMaskFilter(null);
    }

3.嵌入图片

   /**
     * @param bitmap
     */
    public void setImage(Bitmap bitmap) {
        imageToMove = true;
        image = Bitmap.createScaledBitmap(bitmap, getWidth() / 2, getHeight() / 2, true);
        originalImage = image;
        invalidate();
    }

4.颜色更改


    public void setColorBackground(int color) {
        colorBackground = color;
        invalidate();
    }

    public void setSizeBrush(float s) {
        sizeBrush = s;
        mPaint.setStrokeWidth(toPx(sizeBrush));
    }

    public float getSizeBrush() {
        return sizeBrush;
    }

    public void setBrushColor(int color) {
        mPaint.setColor(color);
    }

    public void setSizeEraser(float s) {
        sizeEraser = s;
        mPaint.setStrokeWidth(toPx(sizeEraser));
    }

    public float getSizeEraser() {
        return sizeEraser;
    }

5. 回退

/**
     * 回退
     */
    public void returnLastAction() {
        if (listAction.size() > 0) {
            listAction.remove(listAction.size() - 1);
            if (listAction.size() > 0) {
                bitmapView = listAction.get(listAction.size() - 1);
            } else {
                bitmapView = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            }

            mCanvas = new Canvas(bitmapView);
            invalidate();
        }
    }

6.图片保存

 private void saveBitmap() {
        Bitmap bitmap = mPaintView.getBitmap();
        String fileName = UUID.randomUUID() + ".png";
        File folder = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES) + File.separator + getString(R.string.app_name));
        if (!folder.exists()) {
            folder.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        try {
            Log.d(TAG, "" + folder + File.separator + fileName);
            fileOutputStream = new FileOutputStream(folder + File.separator + fileName);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
            Toast.makeText(this, "照片已保存", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            //刷新文件媒体系统 更新数据库
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                galleryAddPhotoAboveApi28(fileName, folder + File.separator + fileName);
            } else {
                galleryAddPhotoBelowApi28(folder + File.separator + fileName);
            }

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

注意保存后刷新Media数据库,使照片中可以刷新出最新保存的文件

7.预览

  • 预览缩略图
  • 预览大图并实现双指缩放

8.总结

  • View自定义绘制的流程
  • path的运用
  • bitmap的操作
  • 线程的使用
  • 读写权限的添加
  • 触摸onTouchEvent的处理(重点都在这里代码有些多)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值