清明節做了個畫板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的處理(重點都在這裏代碼有些多)

github鏈接 歡迎start

CSDN

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章