接上篇,Android自己定义View工具:Paint&Canvas(二)

上一篇中介绍的Canvas绘制图形仅仅能画一些常规图形(圆。椭圆。矩形等),假设想绘制更复杂的图形。Path神器来了!

Path是什么?

Path类将多种复合路径(多个轮廓,如直线段、二次曲线、立方曲线)封装在其内部的几何路径。

怎样绘制Path:

通过设置Paint的Style(FILL、STROKE、FILL_AND_STROKE),然后调用canvas.drawPath(path, paint)。Path还能够用于剪切或者在路径上绘制文本(canvas.drawTextOnPath())。

Path有两个构造函数:

Path() // 空的构造函数
Path(Path src) //创建一个新的路径。而且从src路径里赋值内容

Path经常用法一览表:

Path经常用法 备注
线操作  
lineTo、rLineTo 绘制线
点操作  
moveTo、rMoveTo 改变后面操作的起始点位置
setLastPoint 改变前面操作中最后点的位置
加入常规图形  
addRect 绘制矩形
addRoundRect 绘制圆角矩形
addCircle 绘制圆
addOval 绘制椭圆
addArc、arcTo 绘制圆弧
闭合path  
close 假设连接Path起点和终点能形成一个闭合图形,则会将起点和终点连接起来形成一个闭合图形
贝塞尔曲线  
quadTo、rQuadTo、cubicTo、rCubicTo 贝塞尔曲线
  • 线操作
lineTo(float x, float y) //加入当前点到目标点(x,y)构成的直线到path
rLineTo(float dx, float dy) //基于当前坐标系,即以path最后的那个点
//为坐标系原点(0,0),假设前面没有path的点,默认是屏幕左上角(0,0).

注:lineTo、rLineTo起始点默认是屏幕左上角的坐标系原点(0,0)!

演示样例:

//设置Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
//设置Path
Path path = new Path();
//屏幕左上角(0,0)到(200,400)画一条直线
path.lineTo(200, 400);
//(200, 400)到(400,600)画一条直线
path.lineTo(400, 600);
//以(400,600)为起始点(0,0)偏移量为(400,600)画一条直线。
//其终点坐标实际在屏幕的位置为(800,1200)
path.rLineTo(400, 600);
canvas.drawPath(path, mPaint);

效果图:

imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="">

  • 点操作
moveTo(float x, float y) //改变接下来操作的起点位置为(x,y)
rMoveTo(float dx, float dy) //接下来要操作的起点位置为(x+dx,y+dy)
setLastPoint(float dx, float dy) //改变前一步操作点的位置。会改变前一步的操作

先来看moveTo和rMoveTo的差别。演示样例:

//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
//初始化Path
Path path = new Path();
//将坐标系原点从(0,0)移动到(100,100)
path.moveTo(100, 100);
//画从(100,100)到(400,400)之间的直线
path.lineTo(400, 400);
//path.rMoveTo(0, 100); //临时凝视
path.lineTo(400, 800);
canvas.drawPath(path, mPaint);

效果图:

imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="">

上面代码中,打开凝视的path.rMoveTo(0,
100)。意为下一步操作起点位置由(400,400)变为(400+0,400+100)即为(400,500),效果图:

接下来看下,moveTo和setLastPoint的差别。相同用上面的代码,加上path.setLastPoint(100,
800)。例如以下:

//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
//初始化Path
Path path = new Path();
//将坐标系原点从(0,0)移动到(100,100)
path.moveTo(100, 100);
//画从(100,100)到(400,400)之间的直线
path.lineTo(400, 400);
//新加的setLastPoint
path.setLastPoint(100, 800);
path.lineTo(400, 800);
canvas.drawPath(path, mPaint);

效果图:

虚线本来是没设置setLastPoint之前的路径,设置setLastPoint(100,800)后。影响到了前一步lineTo(400,400)操作,变成了lineTo(100,800),最后结果就变成了红颜色的path路径,能够得出结论:moveTo影响的是后面操作的起点位置。不会影响之前的操作;而 setLastPoint改变前一步操作最后一个点的位置,不仅影响前一步操作,同一时候也会影响后一步操作!

  • 绘制常规图形
//绘制圆
addCircle(float x, float y, float radius, Direction dir)
//绘制椭圆
addOval(RectF oval, Direction dir)
addOval(float left, float top, float right, float bottom, Direction dir)
//绘制矩形
addRect(RectF rect, Direction dir)
addRect(float left, float top, float right, float bottom, Direction dir)
//绘制圆角矩形
addRoundRect(RectF rect, float rx, float ry, Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx, float ry,Direction dir)
addRoundRect(RectF rect, float[] radii, Direction dir)
addRoundRect(float left, float top, float right, float bottom, float[] radii,Direction dir)

全部方法里面都有一个共同的參数Direction :

Direction 备注
Path.Direction.CCW counter-clockwise ,沿逆时针方向绘制
Path.Direction.CW clockwise 。沿顺时针方向绘制

Direction 使用方法演示样例:

//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2f);
paint.setTextSize(40f);
//初始化Path
Path path = new Path();
//以(600,600)为圆心。300为半径绘制圆
//Path.Direction.CW顺时针绘制圆 Path.Direction.CCW逆时针绘制圆
path.addCircle(600, 600, 300, Path.Direction.CW);
//沿path绘制文字
canvas.drawTextOnPath("痛苦最好是别人的。快乐才是自己的。麻烦将是临时的,朋友总是永恒的。", path, 0, 0, paint);
canvas.drawPath(path, paint);

效果图:

效果非常明显,设置为Path.Direction.CW时,文字沿顺时针绘制;设置为Path.Direction.CCW时。文字沿逆时针绘制。

绘制常规图形演示样例:

//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
Path path = new Path();
//以(400,200)为圆心,半径为100绘制圆
path.addCircle(400, 200, 100, Path.Direction.CW); //绘制椭圆
RectF rectF = new RectF(100, 350, 500, 600);
//第一种方法绘制椭圆
path.addOval(rectF, Path.Direction.CW);
//另外一种方法绘制椭圆
path.addOval(600, 350, 1000, 600, Path.Direction.CW); //绘制矩形
RectF rect = new RectF(100, 650, 500, 900);
//第一种方法绘制矩形
path.addRect(rect, Path.Direction.CW);
//第一种方法绘制矩形
path.addRect(600, 650, 1000, 900, Path.Direction.CCW); //绘制圆角矩形
RectF roundRect = new RectF(100, 950, 300, 1100);
//第一种方法绘制圆角矩形
path.addRoundRect(roundRect, 20, 20, Path.Direction.CW);
//另外一种方法绘制圆角矩形
path.addRoundRect(350, 950, 550, 1100, 10, 50, Path.Direction.CCW);
//第三种方法绘制圆角矩形
//float[] radii中有8个值,依次为左上角,右上角,右下角,左下角的rx,ry
RectF roundRectT = new RectF(600, 950, 800, 1100);
path.addRoundRect(roundRectT, new float[]{50, 50, 50, 50, 50, 50, 0, 0}, Path.Direction.CCW);
//第四种方法绘制圆角矩形
path.addRoundRect(850, 950, 1050, 1100,new float[]{0, 0, 0, 0,50, 50, 50, 50}, Path.Direction.CCW);
canvas.drawPath(path, paint);

效果图:

imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="">

绘制圆弧:

//绘制圆弧
addArc(RectF oval, float startAngle, float sweepAngle)
addArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle) //forceMoveTo:是否强制将path最后一个点移动到圆弧起点,
//true是强制移动。即为不连接两个点。false则连接两个点
arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)
arcTo(RectF oval, float startAngle, float sweepAngle)
arcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo)

addArc和arcTo都是加入圆弧到path中,只是他们之间还是有差别的:addArc是直接加入圆弧到path中。而arcTo会推断要绘制圆弧的起点与绘制圆弧之前path中最后的点是否是同一个点,假设不是同一个点的话,就会连接两个点。

演示样例:

//在(400, 200, 600, 400)区域内绘制一个300度的圆弧
RectF rectF = new RectF(400, 200, 600, 400);
path.addArc(rectF, 0, 300);
//在(400, 600, 600, 800)区域内绘制一个90度的圆弧。而且不连接两个点
RectF rectFTo = new RectF(400, 600, 600, 800);
path.arcTo(rectFTo, 0, 90, true);
//等价于path.addArc(rectFTo, 0, 90);
canvas.drawPath(path, paint);

效果图:

改动一下代码:

//在(400, 200, 600, 400)区域内绘制一个300度的圆弧
RectF rectF = new RectF(400, 200, 600, 400);
path.addArc(rectF, 0, 300);
//在(400, 600, 600, 800)区域内绘制一个90度的圆弧。而且连接两个点
RectF rectFTo = new RectF(400, 600, 600, 800);
path.arcTo(rectFTo, 0, 90,false);
//等价于path.arcTo(rectFTo, 0, 90);
canvas.drawPath(path, paint);

对照发现我们仅仅是将arcTo最后一个參数变成了false。即连接绘制圆弧之前path的最后一个点和绘制圆弧的起点。效果图:

  • 闭合path
path.close();

假设path的终点和起始点不是同一个点的话,close()连接这两个点,形成一个封闭的图形,演示样例:

//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
//初始化Path
Path path = new Path();
//将坐标原点移动到(300,300,)
path.moveTo(300, 300);
//连接(300, 300)和(300, 600)成一条线
path.lineTo(300, 600);
//连接(300, 600)和(600, 600)成一条线
path.lineTo(600, 600);
//path.close();临时凝视
canvas.drawPath(path, paint);

效果图:

改动一下代码。将上面的path.close()打开,效果图:

能够调用close()后,连接了path的起始点和终点形成了一个封闭图形!

贝塞尔曲线内容较多,放在下一篇了!

Android Canvas之Path操作的更多相关文章

  1. 【转】android Graphics(四):canvas变换与操作

    android Graphics(四):canvas变换与操作 分类: 5.andriod开发2014-09-05 15:05 5877人阅读 评论(18) 收藏 举报   目录(?)[+]   前言 ...

  2. android Graphics(四):canvas变换与操作

    前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样.我尽量多画图,让大家更清 ...

  3. Android Canvas绘图详解(图文)

    编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! Andr ...

  4. 【转】Android Canvas绘图详解(图文)

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...

  5. 图形绘制 Canvas Paint Path 详解

    图形绘制简介        Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.大部分2D使用的api都在android.grap ...

  6. 【转】Android Canvas绘图详解

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android中使用图形处理引擎,2D部分是an ...

  7. android canvas d

    (以下转自:http://blog.csdn.net/longyi_java/article/details/6930480) 1.基本的绘制图片方法 //Bitmap:图片对象,left:偏移左边的 ...

  8. 【转】Android Canvas的save(),saveLayer()和restore()浅谈

    Android Canvas的save(),saveLayer()和restore()浅谈 时间:2014-12-04 19:35:22      阅读:1445      评论:0      收藏: ...

  9. Android使用绘图Path总结

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

随机推荐

  1. iOS---Objective-C: +load vs +initialize

    在 NSObject 类中有两个非常特殊的类方法 +load 和 +initialize ,用于类的初始化.这两个看似非常简单的类方法在许多方面会让人感到困惑,比如: 子类.父类.分类中的相应方法什么 ...

  2. A.Equals(B)和A==B的区别

    Equals 和 == 都是用于比较. 如果a和b都是值类型,则a.Equals(b) 和 a == b 结果相同,但是在引用类型是它们的行为是不同的: string a = new string(n ...

  3. openssl-1.0.1c交叉编译动态库(转)

    linux编译相关(13)  版权声明:本文为博主原创文章,未经博主允许不得转载. #交叉编译openssl ------直接修改Makefile新加这一行:CROSS_COMPILE= arm-un ...

  4. cf 235C 后缀自动机

    题目大意 给定字符串\(S\)与\(n<=10^5\)个串\(x_1,x_2...x_n\)(总长\(\le10^6\)) 对于每个\(x_i\),输出有多少个\(S\)的子串与\(x_i\)循 ...

  5. 反射的基本使用以及原理(Class获取方式)

    1.什么是反射技术? 动态获取指定类以及类中的内容(成员),并运行其内容. 应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象.这时可以根据配置文件的类全名去找对应的字节码文件,并加载进 ...

  6. Http协议和Tomcat服务器安装与eclipse集成(重要)

    一.Http协议 1.什么是Http协议 HTTP,超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的     一种网络协议.所有的WWW文件都必须遵守这 ...

  7. 此时不应有 \Microsoft (转)

    原文转自 http://www.tuicool.com/articles/J7RFRz 下载boost库后,在cmd中运行bootstrap.bat ,输出 "此时不应有 \Microsof ...

  8. python编程(python开发的三种运行模式)【转】

    转自:http://blog.csdn.net/feixiaoxing/article/details/53980886 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 单循环 ...

  9. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---41

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  10. Selenium2+python自动化(学习笔记3)

    1.加载firefox配置 参考代码: # coding=utf-8from selenium import webdriver# 配置文件地址,打开Firefox点右上角设置--帮助--故障排除信息 ...