下面这个实例通过前面学过的Paint、Canvas等2D绘画技术来实现一个简单的Android的绘图板。

具体实现代码:

创建一个名为DrawView的类,该类继承自android.view.View类。在该类中,首先定义程序中所需的属性,然后添加构造方法,并重写onDraw(Canvas canvas)方法:
DrawView.java:

package com.example.test;  import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View;  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;//画笔  Bitmap cacheBitmap=null;//定义一个内存中的图片,该图片将作为缓冲区  Canvas cacheCanvas=null;//定义cacheBitmap上的Canvas对象  /*   * 功能:构造方法   * */  public DrawView(Context context, AttributeSet attrs) {   super(context, attrs);     }    /*   * 功能:重写onDraw方法   * */  @Override  protected void onDraw(Canvas canvas) {   super.onDraw(canvas);    } } 

创建布局文件,选择帧布局,并加入上面创建的继承了View的自定义画图控件:
res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>     

在DrawView类的构造方法中,首先获取屏幕的高度和宽度,并创建一个与该View相同大小的缓存区,然后创建一个新的画面,并实例化一个路径,再将内存中的位图绘制到cacheCanvas中,最后实例化一个画笔,并设置画笔的相关属性。
关键代码如下:

/*   * 功能:构造方法   * */  public DrawView(Context context, AttributeSet attrs) {   super(context, attrs);   view_width=context.getResources().getDisplayMetrics().widthPixels;//获取屏幕宽度   view_height=context.getResources().getDisplayMetrics().heightPixels;//获取屏幕高度   //创建一个与该View相同大小的缓存区   cacheBitmap=Bitmap.createBitmap(view_width,view_height,Config.ARGB_8888);   cacheCanvas=new Canvas();//创建一个新的画布   path=new Path();   //在cacheCanvas上绘制cacheBitmap   cacheCanvas.setBitmap(cacheBitmap);   paint=new Paint(Paint.DITHER_FLAG);//Paint.DITHER_FLAG防抖动的   paint.setColor(Color.RED);   //设置画笔风格   paint.setStyle(Paint.Style.STROKE);//设置填充方式为描边   paint.setStrokeJoin(Paint.Join.ROUND);//设置笔刷转弯处的连接风格   paint.setStrokeCap(Paint.Cap.ROUND);//设置笔刷的图形样式(体现在线的端点上)   paint.setStrokeWidth(1);//设置默认笔触的宽度为1像素   paint.setAntiAlias(true);//设置抗锯齿效果   paint.setDither(true);//使用抖动效果  } 

在DrawView类的onDraw()方法中,添加以下代码,用于设置背景颜色、绘制cacheBitmap、绘制路径以及保存当前绘图状态到栈中,并调用restore()方法恢复所保存的状态,关键代码如下:

/*   * 功能:重写onDraw方法   * */  @Override  protected void onDraw(Canvas canvas) {   super.onDraw(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之前保存的状态,防止保存后对canvas执行的操作对后续的绘制有影响   canvas.restore();  } 

在Draw类中,重写onTouchEvent()方法,为该视图添加触摸事件监听器,在该方法中,首先获取触摸事件发生的位置,然后用switch语句对事件的不同状态添加响应代码,最后调用invalidate()方法更新视图。具体代码如下:

@Override  public boolean onTouchEvent(MotionEvent event) {   //获取触摸事件发生的位置   float x=event.getX();   float y=event.getY();   switch(event.getAction()){    case MotionEvent.ACTION_DOWN:     //将绘图的起始点移到(x,y)坐标点的位置     path.moveTo(x, y);     preX=x;     preY=y;     break;    case MotionEvent.ACTION_MOVE:     //保证横竖绘制距离不能超过625     float dx=Math.abs(x-preX);     float dy=Math.abs(y-preY);     if(dx>5||dy>5){       //.quadTo贝塞尔曲线,实现平滑曲线(对比lineTo)      //x1,y1为控制点的坐标值,x2,y2为终点的坐标值      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,表明处理方法已经处理该事件  } 

编写clear()方法,用于实现橡皮擦功能,具体代码如下:

public void clear(){   //设置图形重叠时的处理方式   paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));   //设置笔触的宽度   paint.setStrokeWidth(50);  } 

编写保存当前绘图的save方法,在该方法中,调用saveBitmap()方法将当前绘图保存为PNG图片。save()方法的具体代码如下:

public void save(){   try{    saveBitmap("myPitcture");   }catch(IOException e){    e.printStackTrace();   }     } 

编写保存绘制好的位图的方法saveBitmap(),在该方法中,首先在SD卡上创建一个文件,然后创建一个文件输出流对象,并调用Bitmap类的compress()方法将绘图内容压缩为PNG格式输出到刚刚创建的文件输出流对象中,最后将缓冲区的数据全部写出到输出流中,并关闭文件输出流对象。saveBitmap()方法的具体代码如下:

private void saveBitmap(String fileName) throws IOException {   File file=new File(getSDPath()+fileName+".png");   file.createNewFile();   FileOutputStream fileOS=new FileOutputStream(file);   //将绘图内容压缩为PNG格式输出到输出流对象中   cacheBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS);   fileOS.flush();//将缓冲区中的数据全部写出到输出流中   fileOS.close();//关闭文件输出流对象  }    //获得SD卡的根目录  public String getSDPath(){    File sdDir = null;    boolean sdCardExist = Environment.getExternalStorageState()          .equals(android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在     if (sdCardExist)  //如果SD卡存在,则获取跟目录    {             sdDir = Environment.getExternalStorageDirectory();//获取跟目录    }     return sdDir.toString();      } 

在程序中需要向SD卡上保存文件,那么需要在AndroidManifest.xml文件中赋予相应的权限,
具体代码入下:

    

在res目录中,创建一个menu目录,并在该目录中创建一个名称为toolsmenu.xml的菜单资源文件,在该文件中编写实例中所应用的功能菜单,关键代码如下:

<?xml version="1.0" encoding="utf-8"?>                                                                                        

其中values/strings.xml中:

<?xml version="1.0" encoding="utf-8"?>     test  Hello world!  Settings  画笔颜色  红色  绿色  蓝色  画笔宽度        擦除绘画  保存绘画    

在默认创建的MainActivity中,为实例添加选项菜单。
首先,重写onCreatOptionsMenu()方法,在该方法中,实例化一个MenuInflater对象,并调用该对象的inflate方法解析toolsmenu.xml的菜单资源文件。具体代码如下:

/*   * 创建选项菜单   * */  @Override  public boolean onCreateOptionsMenu(Menu menu) {   MenuInflater inflator=new MenuInflater(this);   inflator.inflate(R.menu.toolsmenu, menu);   return super.onCreateOptionsMenu(menu);  } 

然后,重写onOptionsItemSelected方法,分别对各个菜单项被选择时做出相应的处理,具体代码如下:

/*   * 当菜单项被选择时,做出相应的处理   * */  @Override  public boolean onOptionsItemSelected(MenuItem item) {   //获取自定义的绘图视图   DrawView dv=(DrawView)findViewById(R.id.drawView1);   dv.paint.setXfermode(null);//取消擦除效果   dv.paint.setStrokeWidth(1);//初始化画笔的宽度   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(1);//设置笔触的宽度为1像素     break;    case R.id.width_2:     dv.paint.setStrokeWidth(5);//设置笔触的宽度为5像素     break;    case R.id.width_3:     dv.paint.setStrokeWidth(10);//设置笔触的宽度为10像素     break;    case R.id.clear:     dv.clear();//擦除绘画     break;    case R.id.save:     dv.save();//保存绘画     break;   }   return true;  } 

运行效果如图

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多相关文章

  1. 关于Activity的少许细节
  2. Android(安卓)Studio相关配置Mac版
  3. android builde.gradle 动态配置域名
  4. Android(安卓)Banner轮播控件
  5. 下载Android(安卓)ADT时找不到org.eclipse.wst.sse.core 0.0.0的
  6. android自定义view--绘制顺序及相关原理
  7. 关于Android中Animation的停止
  8. Android基础入门教程——8.1.3 Android中的13种Drawable小结 Par
  9. Android获得所有存储设备位置的最佳方法

随机推荐

  1. Android布局文件-错误
  2. Android faceBook KeyHash生成(生成发布密
  3. Android抖动的EditText
  4. Android屏蔽EditText的软键盘
  5. JavaScript:js 正则表达式判断 Android、i
  6. Android官方命令深入分析之hprof-conv
  7. Android AsyncTask深入分析
  8. android 判断网络连接、sim卡信息以及pin
  9. 修改Android studio生成的apk的名称
  10. 设计模式—建造者模式及实例(BuilderPatte