Path作为Android中一种相对复杂的绘图方式,官方文档中的有些解释并不是很好理解,这里作一个相对全面一些的总结,供日后查看,也分享给大家,共同进步。

1.基本绘图方法

  1. addArc(RectF oval, float startAngle, float sweepAngle)
    绘制弧线,配合Paint的Style可以实现不同的填充效果
  2. addCircle(float x, float y, float radius, Path.Direction dir)
    绘制圆形,其中第dir参数用来指定绘制时是顺时针还是逆时针
  3. addOval(RectF oval, Path.Direction dir)
    绘制椭圆形,其中 oval作为椭圆的外切矩形区域
  4. addRect(RectF rect, Path.Direction dir)
    绘制矩形
  5. addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
    绘制圆角矩形
  6. lineTo(float x, float y)
    绘制直线
  7. addPath(Path src)
    添加一个新的Path到当前Path
  8. arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
    addArc方法相似,但也有区别,下文细述。
  9. quadTo(float x1, float y1, float x2, float y2)
    绘制二次贝塞尔曲线,其中 (x1,y1)为控制点,(x2,y2)为终点
  10. cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
    绘制三次贝塞尔曲线,其中(x1,y1),(x2,y2)为控制点,(x3,y3)为终点

2.rXXX方法

上面的lineTo,MoveTo,QuadTo,CubicTo方法都有与之对应的rXXX方法:

  1. rLineTo(float dx, float dy)
  2. rMoveTo(float dx, float dy)
  3. rQuadTo(float dx1, float dy1, float dx2, float dy2)
  4. rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

这些方法与之对应的原方法相比,惟一的区别在于:r方法是基于当前绘制开始点的offest,比如当前paint位于 (100,100)处,则使用rLineTo(100,100)方法绘制出来的直线是从(100,100)到(200,200)的一条直接,由此可见rXXX方法方便用来基于之前的绘制作连续绘制。

3.Path.op方法

//原型
op(Path path, Path.Op op)
//eg
path1.op(path2,Path.Op.DIFFERENCE);

此方法用于对两个Path对象做相应的运算组合(combine),具体的说是根据不同的op参数及path2参数来影响path1对象,有点类似于数学上的集合运算。请看下面的例子:

Path path1 = new Path();
path1.addCircle(150, 150, 100, Path.Direction.CW);
Path path2 = new Path();
path2.addCircle(200, 200, 100, Path.Direction.CW);
path1.op(path2, Path.Op.DIFFERENCE);
canvas.drawPath(path1, paint1);

效果如下:

通过不断修改path1.op的第二个参数依次可以得到如下效果:

Path.Op.INTERSECT效果:

Path.Op.UNION效果:

Path.Op.REVERSE_DIFFERENCE效果:

Path.Op.XOR效果:

总结:

  1. Path.Op.DIFFERENCE 减去path1中path1与path2都存在的部分;
    path1 = (path1 – path1 ∩ path2)
  2. Path.Op.INTERSECT 保留path1与path2共同的部分;
    path1 = path1 ∩ path2
  3. Path.Op.UNION 取path1与path2的并集;
    path1 = path1 ∪ path2
  4. Path.Op.REVERSE_DIFFERENCE 与DIFFERENCE刚好相反;
    path1 = path2 – (path1 ∩ path2)
  5. Path.Op.XOR 与INTERSECT刚好相反;
    path1 = (path1 ∪ path2) – (path1 ∩ path2)

4.setFillType

设置path的填充模式.网上关于path的FillType的介绍很少,实际上在官方ApiDemos里就有个很好的例子:

/**
* Created by ghui on 10/25/15.
*/
public class PathFillTypeView extends View {
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path mPath; public PathFillTypeView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true); mPath = new Path();
mPath.addCircle(40, 40, 45, Path.Direction.CCW);
mPath.addCircle(80, 80, 45, Path.Direction.CCW);
mPath.addCircle(120, 120, 45, Path.Direction.CCW);
} private void showPath(Canvas canvas, int x, int y, Path.FillType ft,
Paint paint) {
canvas.save();
canvas.translate(x, y);
canvas.clipRect(0, 0, 160, 160);
canvas.drawColor(Color.WHITE);
mPath.setFillType(ft);
canvas.drawPath(mPath, paint);
canvas.restore();
} @Override
protected void onDraw(Canvas canvas) {
Paint paint = mPaint;
paint.setColor(Color.RED);
canvas.drawColor(0xFFCCCCCC);
canvas.translate(20, 20);
paint.setAntiAlias(true);
showPath(canvas, 0, 0, Path.FillType.WINDING, paint);
showPath(canvas, 160 * 2, 0, Path.FillType.EVEN_ODD, paint);
showPath(canvas, 0, 160 * 2, Path.FillType.INVERSE_WINDING, paint);
showPath(canvas, 160 * 2, 160 * 2, Path.FillType.INVERSE_EVEN_ODD, paint);
}
}

效果如下:


(上面的例子在官方ApiDemo的基础上做了适当的修改)

总结:

所谓填充指的就是填充内部,setFillType就是用来界定哪里算内部的算法。在计算机图形学中界定一个点是不是在多边形内部有两种算法:

  1. 非零环绕数规则(Nonzero-rule)
  2. 奇偶规则(Even–odd rule)

关于这两种算法这里不作详细介绍。

5.易混淆的方法

1. addArc 与 arcTo

前者指定在某处画一条弧线,仅此而已,不会受当前paint的位置所影响。而arcTo方法有两种形式:

  1. arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
  2. arcTo(RectF oval, float startAngle, float sweepAngle)对于第一种形式的方法,若forceMoveTo参数为false,则与第二种形式的方法没区别,绘制成的最终图形会受到落笔点的影响;
    若forceMoveTo参数值为true,则绘制效果与addArc方法没有区别。
//代码1
Path path = new Path();
path.moveTo(100, 100);
path.addArc(200, 200, 400, 400, 0, 150);
canvas.drawPath(path, paint);

代码1效果如下图:

//代码2
Path path = new Path();
path.moveTo(100, 100);
path.arcTo(200, 200, 400, 400, 0, 150, false);
canvas.drawPath(path,paint);

代码2效果如下图:

若将代码2中的arcTo方法的参数修改为true则绘制的效果与代码1相同。

2. reset 与 rewind

reset清除path上的内容,重置path到 path = new Path()的初始状态。
rewind清除path上的内容,但会保留path上相关的数据结构,以高效的复用。

其它方法

  1. moveTo(float x,float y)
    移动画笔到 (x,y) 处
  2. offset(float dx, float dy)
    平移当前path,在此path上绘制的任何图形都会受到影响
  3. close()
    闭合当前路径 (系统会自动从起点到终点绘制一条直线,使当前路径闭合)
  4. reset()
    重置path,但不会重置fill-type设置
  5. rewind()
    重置path,但会保留内部数据结构
  6. set(Path src)
    设置新的Path到当前对象
  7. setLastPoint(float x,float y)
    设置当前path的终点
  8. transform(Matrix matrix)
    矩阵变换
 

【转载】Android绘图之Path总结的更多相关文章

  1. Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(上)

    前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有Java层的,也有jni层深入到Framework.Canvas有许多的知识内容,构建了一个武器库一般,所谓十 ...

  2. android 绘图之Path与Paint详解

    /** * Paint类介绍 * * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色, * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法, * 大体上可以分 ...

  3. Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(下)

    LinearGradient 线性渐变渲染器 LinearGradient中文翻译过来就是线性渐变的意思.线性渐变通俗来讲就是给起点设置一个颜色值如#faf84d,终点设置一个颜色值如#CC423C, ...

  4. 论文第5章:Android绘图平台的实现

    面向移动设备的矢量绘图平台设计与实现 Design and Implementation of Mobile Device-oriented Vector Drawing Platform 引用本论文 ...

  5. android 绘图之Canvas,Paint类

    Canvas,Paint 1.在android 绘图但中经常要用到Canvas和Paint类,Canvas好比是一张画布,上面已经有你想绘制图画的轮廓了,而Paint就好比是画笔,就要给Canvas进 ...

  6. Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧

    第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...

  7. 第三章 Android绘图机制与处理技巧

    1.屏幕尺寸信息 屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DPI(Dots Per Inch),它是对 ...

  8. Android群英传笔记——第六章:Android绘图机制与处理技巧

    Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...

  9. Android绘图机制(二)——自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解

    Android绘图机制(二)--自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解 我们要想画好一些炫酷的View,首先我们得知道怎么去画一些基础的图案,比如矩形,圆 ...

随机推荐

  1. Samba CVE-2017-7494验证实验

    漏洞简介 Samba是在Linux和UNIX系统上实现SMB协议的一个软件,不少IoT设备也使用了Samba.2017年5月24日Samba发布了4.6.4版本,修复了一个严重的远程代码执行漏洞,漏洞 ...

  2. iOS---OBJC_ASSOCIATION_ASSIGN可能引起的Crash

    //OBJC_ASSOCIATION_ASSIGN类似于我们常用的assign,assign策略的特点就是在对象释放以后,不会主动将应用的对象置为nil,这样会有访问僵尸对象导致应用崩溃的风险.为了解 ...

  3. inux 磁盘监控分析

    一.查看磁盘空间  1. df -h Size 分割区总容量 Used 已使用的大小 Avail 剩下的大小 Use% 使用的百分比 Mounted on 路径地址 2.查看目录的空间 du -sh  ...

  4. NLP之语言模型

    参考: https://mp.weixin.qq.com/s/NvwB9H71JUivFyL_Or_ENA http://yangminz.coding.me/blog/post/MinkolovRN ...

  5. 【重学Node.js 第5篇】部署项目到腾讯云服务器

    课程介绍看这里:https://www.cnblogs.com/zhangran/p/11963616.html 项目github地址:https://github.com/hellozhangran ...

  6. easybcd误删Win10启动项,UEFI恢复引导

    参考文章https://blog.csdn.net/A_Sen_A/article/details/89545311 想给电脑安Ubuntu双系统,期间根据一些不靠谱的文章用了easybcd软件,Ub ...

  7. 东芝MCU实现位带操作

    位带操作简介 位带操作的概念其实30年前就有了,那还是 8051单片机开创的先河,如今ARM CM3 将此能力进化,可以说,这里的位带操作是8051 位寻址区的威力大幅加强版.即如果要改写某个寄存器的 ...

  8. Apollo 分布式配置中心(补充)

    1.   Namespace 1.1.  什么是Namespace Namespace是配置项的集合,类似于一个配置文件的概念. Apollo在创建项目的时候,都会默认创建一个“application ...

  9. C#/.Net开发入门篇(3)——console类的输入输出

    相信看了我上一篇文章的小伙伴们都知道console这个类的最基本的2个方法了吧,下去练习过的小伙伴应该能知道4个方法. 那么下面我们就来介绍一下上期没有介绍完的另外2个方法Console.WriteL ...

  10. CSS学习笔记-过渡模块

    过渡模块:    1.过渡三要素        1.1必须要有属性发生变化        1.2必须告诉系统哪个属性需要执行过渡效果        1.3必须告诉系统过渡效果持续时长    2.格式: ...