说明:实现了绘画、橡皮擦、嵌入图片、更改颜色、回退,图片分享、保存、预览等功能
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的处理(重点都在这里代码有些多)