Android中怎么实现一个绘图板

发布时间:2021-06-28 17:54:27 作者:Leah
来源:亿速云 阅读:144

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"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 android:id="@+id/frameLayout1" 
 android:orientation="vertical" 
 > 
 <com.example.test.DrawView 
  android:id="@+id/drawView1" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent"/> 
</FrameLayout>

在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文件中赋予相应的权限,
具体代码入下:

<!-- 执行SD卡检查的权限 --> 
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 
<!-- SD卡写入权限 --> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

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

<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android" > 
 <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> 
    <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/clear" android:title="@string/clear"/> 
 <item android:id="@+id/save" android:title="@string/save"/> 
</menu>

其中values/strings.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
  
 <string name="app_name">test</string> 
 <string name="hello_world">Hello world!</string> 
 <string name="action_settings">Settings</string> 
 <string name="color">画笔颜色</string> 
 <string name="color_red">红色</string> 
 <string name="color_green">绿色</string> 
 <string name="color_blue">蓝色</string> 
 <string name="width">画笔宽度</string> 
 <string name="width_1">细</string> 
 <string name="width_2">中</string> 
 <string name="width_3">粗</string> 
 <string name="clear">擦除绘画</string> 
 <string name="save">保存绘画</string> 
  
</resources>

在默认创建的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; 
 }

关于Android中怎么实现一个绘图板问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

推荐阅读:
  1. Android 中怎么实现一个菜单资源
  2. Android中怎么实现一个分享控件

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

android

上一篇:Android中怎么通过自定义ViewGroup实现一个弹性滑动效果

下一篇:Android中怎么实现解释器模式

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》