需求功能详解

单纯的编辑图片的功能,能够在界面上进行图形的绘制,线条的涂鸦,和画马赛克的绘制,并且有撤销的功能。话不多说,直接看一下效果吧:

图片编辑效果

主要实现思路

实现一个自定义View,重写onDraw(),集成这些编辑功能。

功能集成

该编辑功能有涂鸦,画图形,画文字,和马赛克的功能,这里只对除了文字的内容进行介绍,若想进一步获得文字功能,可在代码库中pull代码,并自己打开该功能:

public enum MODE {

NONE, GRAPH_MODE, DOODLE_MODE, MOSAIC_MODE, DRAG, ZOOM

}

涂鸦

先说最简单的涂鸦吧,涂鸦功能实际就是在界面上画线,路径跟着手指移动就完事了。由于有撤销的功能,所以需要把Path都保存起来,在按下时new Path(),并且moveTo按下的位置,在手指移动过程中,将这条path lineTo相对应的位置,手指抬起时结束,那么一条路径不就画完了吗!

/**

* 涂鸦的路径

*/

private ArrayList mDoodlePath = new ArrayList<>();

涂鸦功能的实例:

/**

* 记录画笔和画图的路径,主要用来撤销画图的操作

*/

class DrawPathBean {

public Path path;

public Paint paint;

public MODE mode;

DrawPathBean(Path path, Paint paint, MODE mode) {

this.paint = paint;

this.path = path;

this.mode = mode;

}

}

为了之后的撤销操作,需要将路径记录下来。

在Action_Down中新建画笔和路径,并添加到List中,

// 设置对应mode的画笔

setModePaint(mMode);

mTempPath = new Path();

mStartX = mMoveX;

mStartY = mMoveY;

mTempPath.moveTo(mStartX, mStartY);

// 把path加到队列中

DrawPathBean pathBean = new DrawPathBean(mTempPath, mTempPaint, mMode);

mPaths.add(mMode);

if (mMode == MODE.DOODLE_MODE) {

mDoodlePath.add(pathBean);

} else if (mMode == MODE.MOSAIC_MODE) {

mMosaicPath.add(pathBean);

}

在Action_Move时,只要将最后一条路径的path读取出来,移动到手指所到的位置即可:

if (mMode == MODE.DOODLE_MODE && mDoodlePath.size() > 0) {

mDoodlePath.get(mDoodlePath.size() - 1).path.lineTo(mMoveX, mMoveY);

}

然后在Action_Up的时候,将临时的路径和画笔变量清空,即可:

mTempPath = null;

mTempPaint = null;

最后一步:在onDraw()中,将该数组中保存的路径绘制出来:

if (mDoodlePath.size() > 0) {

for (DrawPathBean pathBean : mDoodlePath) {

canvas.drawPath(pathBean.path, pathBean.paint);

}

}

撤销

有了路径,那么撤销操作就很简单了,只要将数组中最后一条清除,再重绘界面,那么撤销操作就完成了。这里的代码综合了所有操作的撤销动作,涂鸦的只需要看Doodle相关即可:

/**

* 撤销操作

*

* @return 撤销后剩余可以撤销的步骤

*/

public int revertPath() {

int size = mPaths.size();

if (size > 0) {

// 根据最后一位数的mode,删除对应path

MODE lastestMode = mPaths.get(size - 1);

if (lastestMode == MODE.DOODLE_MODE && mDoodlePath.size() > 0) {

mDoodlePath.remove(mDoodlePath.size() - 1);

} else if (lastestMode == MODE.MOSAIC_MODE && mMosaicPath.size() > 0) {

mMosaicPath.remove(mMosaicPath.size() - 1);

} else if (lastestMode == MODE.GRAPH_MODE && mGraphPath.size() > 0) {

mGraphPath.remove(mGraphPath.size() - 1);

}

mPaths.remove(size - 1);

}

postInvalidate();

return size;

}

mPath是三种路径的总和,不管是涂鸦,图形,或是马赛克,都需要将该操作存入mPath,然后撤销时,根据存入的类型,对该类型的路径进行相对应的撤销操作。

至此,一个完整的涂鸦功能就完成了~

android 图片字体涂鸦,Android 编辑图片 Canvas画图,涂鸦,马赛克等(一)相关推荐

  1. android图片保存形式,Android应用开发之Android ScrollView截图和图片保存到相册的方式...

    本文将带你了解Android应用开发之Android ScrollView截图和图片保存到相册的方式,希望本文对大家学Android有所帮助. 1.1首先来看你一种截取屏幕,这种代码有缺陷,只能截取一 ...

  2. android图片分辨率改变,android 通过修改图片像素实现CircleImageView

    CircleImageView实现方法有很多种,各有优缺点,因此需要按照不同的场景使用.我们今天使用修改图片像素的方法实现CircleImageView,主要知识点无非是勾股定理和点到圆形的距离. 素 ...

  3. Android通知栏字体大小,Android通知栏介绍与适配总结(上篇)

    此文已由作者黎星授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 由于历史原因,Android在发布之初对通知栏Notification的设计相当简单,而如今面对各式各样的通知 ...

  4. android程序字体大小,Android如何动态调整应用字体大小详解

    前言 为什么要动态设置字体大小?由于项目面对的是中老年客户项目中自带的字体无法满足客户需求. Android应用字体大小默认随系统设置的字体大小而变化,但您可能不希望您的应用字体大小随系统设置变化,想 ...

  5. android程序字体大小,Android 动态调整应用字体大小

    Android应用字体大小默认随系统设置的字体大小而变化,但您可能不希望您的应用字体大小随系统设置变化,想要自己控制,例如微信.本文简单介绍一下如何实现应用字体大小动态调整而不是依赖系统设置 字体大小 ...

  6. android 镂空字体下载,Android——自定义镂空掩饰控件

    刚学完ViewDragHelper和PorterDuffXferMode的我,突然想做一个这样效果的自定义控件:点击ListView的列表项,通过ViewDragHelper用动画方式上下各弹出一个控 ...

  7. android textview 字体阴影,Android TextView加上阴影效果

    废话不多说直接说关键的: 字体阴影需要四个相关参数: 1. android:shadowColor:阴影的颜色2. android:shadowDx:水平方向上的偏移量3. android:shado ...

  8. android切换字体颜色,Android开发实现按钮点击切换背景并修改文字颜色的方法

    本文实例讲述了Android开发实现按钮点击切换背景并修改文字颜色的方法.分享给大家供大家参考,具体如下: 其实原理很简单,用到的是selector,用来设置android:background和an ...

  9. android开发字体样式,Android开发中修改程序字体的样式

    Android提供三种字体:"Sans","serif"和"monospace". 1.在Android XML文件中设置字体 可以采用an ...

  10. android 图片查看动画,Android 共享动画实现点击列表图片跳转查看大图页面

    主要内容使用系统提供的 API 实现共享动画 在实现过程中遇到的问题图片点击和关闭之后会出现短暂的黑屏问题实现的动画效果如下: 共享动画.gif 具体实现这个效果是在两个页面之间的切换动画,既然是两个 ...

最新文章

  1. 向Python女神推荐这些年我追过的经典书籍
  2. Farseer:一个用于Silverlight和XNA的开源物理引擎
  3. 微信 账户升级服务器地址,微信支付商户平台账户升级后有哪些新功能呢?
  4. vue : 本地调试跨域问题的解决办法:proxyTable
  5. 这一晚注定属于C罗!回归首秀梅开二度,现场超过7万球迷见证这场胜利
  6. 使用composer安装laravel
  7. 服务器固件降级需要重装系统吗,bios降级,小编教你bios可以降级吗
  8. A1008 Elevater(20)
  9. Java美颜相机(1)图像处理
  10. 新年,未知的开始---Created by 思贤泪自潸
  11. 树莓派驱动数码管c 语言,用树莓派驱动八段数码管实现倒计时
  12. 工业镜头倍率及视场范围、焦距的计算方法
  13. 特步公布全新战略定位世界级中国跑鞋;电通集团计划过渡到新的全球集成领导架构 | 美通企业日报...
  14. android 系统源码分析
  15. 【集训Day1】 Dwarves line up
  16. (arxiv-2018)图像检索的注意力感知广义平均池化
  17. CSS的水平居中、垂直居中和水平垂直居中
  18. Advanced Installer多语言包安装
  19. 配置BGP SOO(防环)实例
  20. 数字孪生智慧园区教学实训平台建设研究案例

热门文章

  1. MySQL版本号后面包含“-log”代表什么意思?
  2. 一个人靠不靠谱,就看这 8 个细节
  3. 企查查之seleium自动化操作
  4. 基于Java的大型网站设计方案
  5. 德莱联盟(判断线段是否相交)
  6. AD(altium designer)15原理图与PCB设计教程(十)——信号完整性分析
  7. [数据挖掘] 朴素贝叶斯 以及西瓜集特征工程
  8. 《Miss Talk》第07期:对话拓课云联合创始人兼CTO 王晓伟
  9. ubuntu 12.04中搭建nfs服务器
  10. [angular1.6]Error: “transition superseded“ ui-router 在angular1.6 报错误问题解决