该程序实现画画板的功能,可以调节画笔的大小以及颜色,png图片可以保存到本地或者相册中,同时带有清除画板以及橡皮檫等基本功能。
DrawActivity的CODE:
package com.example.drawfreedom; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.os.Environment; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; public class DrawActivity extends Activity { static int i=0,j=0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.getFilesDir(); PermisionUtils.verifyStoragePermissions(this); //获取手机SD卡读取权限 } // 创建选项菜单 @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflator = new MenuInflater(this);//实例化一个MenuInflater对象 inflator.inflate(R.menu.toolsmenu, menu); //解析菜单文件 return super.onCreateOptionsMenu(menu); } // 当菜单项被选择时,作出相应的处理 @Override public boolean onOptionsItemSelected(MenuItem item) { DrawView dv = (DrawView) findViewById(R.id.drawView1); //获取自定义的绘图视图 dv.paint.setXfermode(null); //取消擦除效果 dv.paint.setStrokeWidth(5); //初始化画笔的宽度 switch (item.getItemId()) { case R.id.red: dv.paint.setColor(Color.RED); //设置画笔的颜色为红色 item.setChecked(true); break; case R.id.green: dv.paint.setColor(Color.GREEN); //设置画笔的颜色为绿色 item.setChecked(true); break; case R.id.blue: dv.paint.setColor(Color.BLUE); //设置画笔的颜色为蓝色 item.setChecked(true); break; case R.id.width_1: dv.paint.setStrokeWidth(5); //设置笔触的宽度为1像素 break; case R.id.width_2: dv.paint.setStrokeWidth(10); //设置笔触的宽度为5像素 break; case R.id.width_3: dv.paint.setStrokeWidth(15);//设置笔触的宽度为10像素 break; case R.id.clear: dv.clear(); //橡皮檫 break; case R.id.back: dv.back(); //返回上一步 break; case R.id.nothing: dv.nothing(); //清屏 //DrawView dv1 = (DrawView) findViewById(R.id.drawView1); break; case R.id.save: { j=0; dv.save(i,j);i++; //保存绘画到APP目录 break; } case R.id.save_camera: { j=1; dv.save(i,j);i++; if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))//若是获取权限失败,提示手动获取 Toast.makeText(DrawActivity.this, "获取权限失败,请手动授权", Toast.LENGTH_SHORT).show(); break; }//保存绘画到相册 } return true; } }
DrawView继承自View,CODE:
package com.example.drawfreedom; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.net.Uri; import android.os.Environment; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; @SuppressLint("DrawAllocation") public class DrawView extends View { private int view_width = 0; //屏幕的宽度 private int view_height = 0; //屏幕的高度 private float preX; //起始点的x坐标值 private float preY;//起始点的y坐标值 private Path path; //路径 public Paint paint = null; //画笔 Bitmap cacheBitmap = null;// 定义一个内存中的图片,该图片将作为缓冲区 Canvas cacheCanvas = null;// 定义cacheBitmap上的Canvas对象 public DrawView(Context context, AttributeSet set) { super(context, set); view_width = context.getResources().getDisplayMetrics().widthPixels; // 获取屏幕的宽度 view_height = context.getResources().getDisplayMetrics().heightPixels; // 获取屏幕的高度 System.out.println(view_width + "*" + view_height); // 创建一个与该View相同大小的缓存区 cacheBitmap = Bitmap.createBitmap(view_width, view_height, Config.ARGB_8888); cacheCanvas = new Canvas(); path = new Path(); cacheCanvas.setBitmap(cacheBitmap);// 在cacheCanvas上绘制cacheBitmap paint = new Paint(Paint.DITHER_FLAG); paint.setColor(Color.GREEN); // 设置默认的画笔颜色 // 设置画笔风格 paint.setStyle(Paint.Style.STROKE); //设置填充方式为描边 paint.setStrokeJoin(Paint.Join.ROUND); //设置笔刷的图形样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置画笔转弯处的连接风格 paint.setStrokeWidth(5); // 设置默认笔触的宽度为5像素 paint.setAntiAlias(true); // 使用抗锯齿功能 paint.setDither(true); // 使用抖动效果 } @Override public void onDraw(Canvas canvas) { canvas.drawColor(0xFFFFFFFF); //设置背景颜色 Paint bmpPaint = new Paint(); //采用默认设置创建一个画笔 canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint); //绘制cacheBitmap canvas.drawPath(path, paint); //绘制路径 canvas.save(Canvas.ALL_SAVE_FLAG); //保存canvas的状态 //canvas.restore(); //恢复canvas之前保存的状态,防止保存后对canvas执行的操作对后续的绘制有影响 } @Override public boolean onTouchEvent(MotionEvent event) { // 获取触摸事件的发生位置 float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(x, y); // 将绘图的起始点移到(x,y)坐标点的位置 preX = x; preY = y; break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(x - preX); float dy = Math.abs(y - preY); if (dx >= 5 || dy >= 5) { // 判断是否在允许的范围内 path.quadTo(preX, preY, (x + preX) / 2, (y + preY) / 2); preX = x; preY = y; } break; case MotionEvent.ACTION_UP: cacheCanvas.drawPath(path, paint); //绘制路径 path.reset(); break; } invalidate(); return true; // 返回true表明处理方法已经处理该事件 } public void clear() { paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint.setColor(Color.BLUE); paint.setStrokeWidth(50); //设置笔触的宽度 //invalidate(); } public void back() { Canvas canvas=new Canvas(); canvas.restore(); } public void nothing() { cacheBitmap=null; // 创建一个与该View相同大小的缓存区 cacheBitmap = Bitmap.createBitmap(view_width, view_height, Config.ARGB_8888); cacheCanvas = new Canvas(); cacheCanvas.setBitmap(cacheBitmap);// 在cacheCanvas上绘制cacheBitmap invalidate(); } public void save(int i,int j) { //int i=0; try { saveBitmap("DrawingPicture","DrawingPicture_"+i,j); } catch (IOException e) { e.printStackTrace(); } } // 保存绘制好的位图到APP目录下 public void saveBitmap(String filesize,String fileName,int j) throws IOException { String directoryPath; directoryPath=getFilePath(getContext(),filesize,fileName,j); //directoryPath=getFilePath(getContext(),filesize,fileName,j); File file = new File(directoryPath ); //创建文件对象 try { file.createNewFile(); //创建一个新文件 FileOutputStream fileOS = new FileOutputStream(file); //创建一个文件输出流对象 cacheBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS); //将绘图内容压缩为PNG格式输出到输出流对象中 fileOS.flush(); //将缓冲区中的数据全部写出到输出流中 fileOS.close(); //关闭文件输出流对象 Toast.makeText(getContext(), "成功保存到"+directoryPath, Toast.LENGTH_SHORT).show();//垴村成功,提示保存的路径 }catch (Exception e) { Toast.makeText(getContext(), e.toString(), Toast.LENGTH_LONG).show();//保存失败,提示原因 } Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri uri = Uri.fromFile(file); intent.setData(uri); getContext().sendBroadcast(intent);//这个广播的目的就是更新图库,发了这个广播进入相册就可以找到你保存的图片了!,记得要传你更新的file哦 } public static String getFilePath(Context context,String filesize,String dir,int j) { //获取APP当前目录并且设置图片保存路径 String directoryPath=""; if(j==0) { //判断SD卡是否可用 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ) { directoryPath =context.getExternalFilesDir(filesize).getAbsolutePath()+File.separator+ dir + ".png"; // directoryPath =context.getExternalCacheDir().getAbsolutePath() ; }else{ //没内存卡就存机身内存 directoryPath=context.getFilesDir().getAbsolutePath() +File.separator +filesize+File.separator + dir + ".png"; // directoryPath=context.getCacheDir()+File.separator+dir; }} else { directoryPath =Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DCIM +File.separator+"Camera"+File.separator+dir + ".png"; // File file = new File(directoryPath); //if(!file.exists()){//判断文件目录是否存在 // file.mkdirs(); //directoryPath=directoryPath+File.separator+dir + ".png"; } //LogUtil.i("filePath====>"+directoryPath); //} return directoryPath; } }
toolsmenu.xml文件
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/back" android:title="@string/back"/> <item android:title="@string/color"> <menu > <!-- 定义一组单选菜单项 --> <group android:checkableBehavior="single" > <!-- 定义子菜单 --> <item android:id="@+id/red" android:title="@string/color_red"/> <item android:id="@+id/green" android:title="@string/color_green"/> <item android:id="@+id/blue" android:title="@string/color_blue"/> </group> </menu> </item> <item android:title="@string/width"> <menu > <!-- 定义子菜单 --> <group android:checkableBehavior="single"> <item android:id="@+id/width_1" android:title="@string/width_1"/> <item android:id="@+id/width_2" android:title="@string/width_2"/> <item android:id="@+id/width_3" android:title="@string/width_3"/> </group> </menu> </item> <item android:id="@+id/nothing" android:title="@string/nothing"/> <item android:id="@+id/clear" android:title="@string/clear" android:icon="@drawable/cha"/> <item android:id="@+id/save" android:title="@string/save"/> <item android:id="@+id/save_camera" android:title="@string/save_camera"/> </menu>
main.xml的CODE,main记得链接DrawView视图:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.example.drawfreedom.DrawView android:id="@+id/drawView1" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
获取SD卡权限:
在MainActivityfest中:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>