1、为自定义View画空白图
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mBimap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);//当该View尺寸发生改变的时候执行 canvas = new Canvas(mBimap); }
2、为自定义View设置触摸事件
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX();//event.getRawX()相对手机屏幕的坐标,event.getX()为相对于ImageView的坐标 float y = event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: touchDown(x,y); invalidate(); break; case MotionEvent.ACTION_MOVE: touchMove(x,y); invalidate(); break; case MotionEvent.ACTION_UP: touchUp(x,y); invalidate();//对该View进行刷新 break; } return true; } private void touchUp(float x, float y) { mPath.lineTo(mX,mY); canvas.drawPath(mPath, mPaint); //清空path mPath.reset(); } private void touchMove(float x, float y) { mPath.quadTo(mX,mY,x,y); canvas.drawPath(mPath,mPaint); mX = x; mY = y; } private void touchDown(float x, float y) { mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; }tips: moveTo、lineTo、quadTo、cubicTo、arcTo的作用 https://segmentfault.com/a/1190000000721127
3、设置画笔的颜色、浮雕、模糊效果
mPaint = new Paint(); mPaint.setAntiAlias(true);//抗锯齿 mPaint.setDither(true);//开启抖动 mPaint.setColor(0xFFFF0000); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND);//设置结合处的样子 mPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔笔刷的类型 mPaint.setStrokeWidth(12); /** direction 是float数组,定义长度为3的数组标量[x,y,z],来指定光源的方向 ambient 取值在0到1之间,定义背景光 或者说是周围光 specular 定义镜面反射系数。 blurRadius 模糊半径。 */ mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f); /** * radius 模糊的半径 * style 模糊的样式 */ mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
@Override public boolean onOptionsItemSelected(MenuItem item) { mPaint.setXfermode(null); mPaint.setAlpha(0xFF); switch (item.getItemId()){ case R.id.menu_color: break; case R.id.menu_emboss: if(mPaint.getMaskFilter() != mEmboss){ mPaint.setMaskFilter(mEmboss); }else{ mPaint.setMaskFilter(null); } break; case R.id.menu_blur: if(mPaint.getMaskFilter() != mBlur){ mPaint.setMaskFilter(mBlur); }else{ mPaint.setMaskFilter(null); } break; case R.id.menu_ease: mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); break; case R.id.menu_srcatop: mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); mPaint.setAlpha(0x80); break; } return true; }
在Android4.0以上可能看不到浮雕、模糊效果,需要在该Activity设置android:hardwareAccelerated="false"
最后保存图片FileOutputStream outputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG,80,outputStream); outputStream.close();
保存之后并不能在图库中看到,在这里要需要通知SDCard重新挂载
由于在KITKAT版本,查看core/res/AndroidManifest.xml你将注意到那个广播android.intent.action.MEDIA_MOUNTED是被保护的,那将意味着他是一个仅仅被系统可以发送的广播
<protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED" />
因此你需要使用其它的方法来fix it,像ACTION_MEDIA_SCANNER_SCAN_FILE或者MediaScannerConnection
Intent intent = new Intent(); intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(file)); sendBroadcast(intent);
或者
MediaScannerConnection.scanFile(this, new String[]{file.getAbsolutePath()}, null, new MediaScannerConnection.MediaScannerConnectionClient() { @Override public void onMediaScannerConnected() { } @Override public void onScanCompleted(String path, Uri uri) { } });使用Intent.ACTION_MEDIA_SCANNER_SCAN_FILE适用于所有的版本,而MediaScannerConnnetion只能用在Android2.3之后。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Intent mediaScanIntent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri contentUri = Uri.fromFile(out); \\out is your output file mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); } else { sendBroadcast(new Intent( Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); }