說明:實現了繪畫、橡皮擦、嵌入圖片、更改顏色、回退,圖片分享、保存、預覽等功能
0.截圖如下
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的處理(重點都在這裏代碼有些多)