大家看过我上两篇博客[画图板一](http://blog.csdn.net/songhengqian/article/details/51792420),[画图板二](http://blog.csdn.net/songhengqian/article/details/51822207)肯定对接下来的内容不陌生了,画图板一开始无非就是我们准备好画笔paint,画在什么上呢? 那就再找个画布canvas,有了笔有了画布那画成啥样,OK我们找来了画笔路径path,三者找齐在触摸方法拿到我们触摸的点,那么最简单的画图板就实现了。我们这么一分析下来发现是不是很简单,其实加上其他的功能也不难,那么我们就来分析下如何实现笔画的恢复和撤销。
我们的画图板里有橡皮,其实可以不加撤销删除,如果加上有点鸡肋的感觉,不过为了给大家分享知识就加上来讲解讲解。对于笔画的撤销与恢复我们很容易就能够想到,撤销我们就把每次的path保存起来,把最上面的移除再把其他的路径重新绘制上去就OK了,恢复更简单,把我们撤销的保存到集合中,从集合中拿出来重新画上就没问题了。
    //view的原宽高private int oldWidth;private int oldHeight;/*** 保存路径的集合*/private ArrayList<DrawPath> savePath;private ArrayList<DrawPath> deletePath;private DrawPath dp;/*** 路径对象**/class DrawPath {Path path;Paint paint;}
有了保存路径的集合我们可以写撤销和恢复的方法了
  /*** 撤销笔画操作*/public void undo() {if (savePath != null && savePath.size() > 0) {initCanvas();// 将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中DrawPath drawPath = savePath.get(savePath.size() - 1);deletePath.add(drawPath);savePath.remove(savePath.size() - 1);// 将路径保存列表中的路径重绘在画布上Iterator<DrawPath> iter = savePath.iterator(); // 重复保存while (iter.hasNext()) {DrawPath dp = iter.next();mCanvas.drawPath(dp.path, dp.paint);}invalidate();}}/*** 恢复笔画操作*/public void redo() {if (deletePath != null && deletePath.size() > 0) {// 将删除的路径列表中的最后一个,也就是最顶端路径取出(栈),并加入路径保存列表中DrawPath dp = deletePath.get(deletePath.size() - 1);savePath.add(dp);// 将取出的路径重绘在画布上mCanvas.drawPath(dp.path, dp.paint);// 将该路径从删除的路径列表中去除deletePath.remove(deletePath.size() - 1);invalidate();}}// 初始化画布函数以清空画布private void initCanvas() {setFocusableInTouchMode(true);setFocusable(true);/* 初始化画笔 */initPaint();mCanvas = new Canvas();mPath = new Path();bitmap_bg=null;bitmap_fg=null;onSizeChanged(bitmapWidth, bitmapHeight, oldWidth, oldHeight);}/*** 清屏*/public void clearPaint() {initCanvas();invalidate();savePath.clear();deletePath.clear();}

然后我们每次开始画的时候创建一个新的path对象,完成之后保存到savePath集合中,

  case MotionEvent.ACTION_DOWN:if (paintState==paint.PEN){mPath = null;mPath = new Path();dp = new DrawPath();dp.path = mPath;dp.paint = mPaint;mPath.reset();}else if (paintState==paint.ERASER){mPath = null;mPath = new Path();dp = new DrawPath();dp.path = mPath;dp.paint = mEraser;mPath.reset();}onTouchDown(event);invalidate();break;case MotionEvent.ACTION_UP:if(paintState==paint.NONE) {// 手指离开屏幕时将临时值还原lastXMove = -1;lastYMove = -1;}else {onTouchUp(event);savePath.add(dp);
//                    mPath = null;invalidate();MainActivity.activity.runOnUiThread(new Runnable() {@Overridepublic void run() {if (MainActivity.activity.getBackBtn().getVisibility()==GONE&& savePath!=null && savePath.size()!=0){MainActivity.activity.getBackBtn().setVisibility(VISIBLE);MainActivity.activity.getBackHoverBtn().setVisibility(GONE);}}});}break;
这里基本就是在down中创建新的path,在up中保存到集合,比较简单。相信大家看了一定会想着太简单了,对,只要你愿意去梳理一切就是这么简单,写完这一篇我们的画图板基本写的差不错了,剩下的就是保存和viewpager视图预览了,希望大家继续关注。
下载源码地址:[画图板三](http://download.csdn.net/detail/songhengqian/9573533)

一个功能强大的画图板(三)相关推荐

  1. 一个功能强大的画图板(二)

    我们在上一篇博客画图板一:[画图板一](http://blog.csdn.net/songhengqian/article/details/51792420)中基本实现了绘画的功能,那么我们就要丰富我 ...

  2. 一个具有一些功能的网络画图板

    前面讲了怎么去实现一个画线数据的传送,今天这个博文我将为大家分享一个具有一些特定功能的网络画图板 实现功能: 能改变颜色,画直线.圆形.矩形.随笔画 功能实现: 这些功能前面说了,是可以理解为不同的数 ...

  3. Android-如何开发一个功能强大的图片选择器

    图片选择器是Android开发中会经常用到的一个功能,特别对于社交类的应用,比如头像设置,比如发图片.自然ImagePicker的轮子很多,今天介绍一个功能强大的轮子SImagePicker 介绍 首 ...

  4. 原生python自带的ide_python自带的IDE是一个功能强大的IDE

    [多选题]关于炒炭存性说法正确的有( ) [单选题](    )是著作权实现其著作财产权的主要方式. [单选题]以下哪个不属于创新成果?(    ) [单选题]下列哪一项不属于无人机配送的优势 [单选 ...

  5. LFTP : 一个功能强大的命令行FTP程序

    LFTP : 一个功能强大的命令行FTP程序 大家好,这篇文章是介绍Lftp以及如何在Linux操作系统下安装的.Lftp是一个基于命令行的文件传输软件(也被称为FTP客户端),由Alexander ...

  6. 一个功能强大超级好用的图表组件Dundas Chart

    最近因为项目需要,需要为客户的统计数据生成图表,包括柱状图和饼图.我找来了Dundas Software的Dundas Chart,大家可以上它的网站http://www.dundas.com/查看最 ...

  7. letter-shell | 一个功能强大的嵌入式shell

    嵌入式开源项目精选专栏 本专栏由Mculover666创建,主要内容为寻找嵌入式领域内的优质开源项目,一是帮助开发者使用开源项目实现更多的功能,二是通过这些开源项目,学习大佬的代码及背后的实现思想,提 ...

  8. Ledger-复式记账的一个功能强大的命令行工具

    无论你是一个电脑极客还是普通用户,记录账户开销总是必不可少的.虽然在Linux上有很多基于GUI的记账工具(比如 - GNUCash)受到大家欢迎,但是工作在命令行的记账工具是很多用户难以想象的.在本 ...

  9. Jcrop是一个功能强大的图像裁剪引擎

    Jcrop是一个功能强大的图像裁剪引擎jQuery的. 它的设计使开发人员可以很容易地直接集成了先进的图像裁剪功能集成到任何基于Web的应用程序在不牺牲动力和灵活性(或编码,测试和调试的星期).Jcr ...

最新文章

  1. Google工作10年,关于技术、管理和职场生涯的一些感悟
  2. Vigenère 密码
  3. JavaScript响应键盘不再用KeyboardEvent.keyCode,而是用keyboardEvent.code
  4. Android中利用ant进行多渠道循环批量打包(一)
  5. Echarts 自定义数据视图
  6. 18、java中的泛型
  7. 工业以太网交换机的三种转发方式
  8. web前端好学吗?如何能提高CSS编写技巧 提高Web前端开发效率
  9. 大数据分析常见的9个错误
  10. 短信转移到另一个手机接收_如何将iPhone手机接收短信同步到另外一台设备上?...
  11. ChannelHandler 接口继承关系图
  12. 小米便签源码分析——data包
  13. shader基础学习摘要(一)
  14. 人脸识别门禁系统设计(一)
  15. 开源分布式定时任务框架技术选型
  16. linux移除硬盘命令,在Linux中在线添加及移除SCSI硬盘方法
  17. 基于STM32设计的健康检测设备(测温心率计步)
  18. 苹果电脑如何打印文件
  19. nginx实现路由转发
  20. 临时邮箱怎么用?邮箱客户端设置

热门文章

  1. 原生APP和Web APP的区别
  2. 关于jvm-java中init与clint区别
  3. 数据密集、计算密集、IO密集
  4. 云计算技术与应用 -基础概念与分布式计算
  5. 一文总结图像生成必备经典模型(一)
  6. 用C语言编写2048游戏
  7. C/C++制作益智游戏:2048(源码详解)
  8. Spring Integration 系统集成
  9. ABOV单片机内部WT时钟RTC的代码实现讲解及示例代码-[MC96F6332D]
  10. flutter 之顶部搜索栏SearchDelegate