#Paint类使用详解
Paint 代表了Canvas上的画笔、画刷、颜料等等

方法 作用
setARGB(int a, int r, int g, int b) 设置Paint对象颜色,参数一为alpha透明通道
setAlpha(int a) 设置alpha不透明度,范围为0~255
setMaskFilter(MaskFilter maskfilter) 滤镜效果
setStyle(Style style); 设置画笔风格
setStrokeWidth(int width) 设置画笔空心线宽
setDither(boolean dither) 设定是否使用图像抖动处理,使绘制出的图片颜色更平滑饱满,图像更加清晰
setAntiAlias(boolean aa) 是否抗锯齿
setColor(int color) 设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义
setFakeBoldText(boolean fakeBoldText) 设置伪粗体文本
setLinearText(boolean linearText) 设置线性文本
setPathEffect(PathEffect effect) 设置路径效果
setRasterizer(Rasterizer rasterizer 设置光栅化
setShader(Shader shader) 设置阴影
setTextAlign(Paint.Align align) 设置文本对齐
setTextScaleX(float scaleX) 设置文本缩放倍数,1.0f为原始
setTextSize(float textSize) 设置字体大小
setTypeface(Typeface typeface) 设置字体,Typeface包含了字体的类型,粗细,还有倾斜、颜色等。
setUnderlineText(boolean underlineText) 设置下划线
setStrokeCap(CAP cap) 线段末端效果
setStrokeJoin(Join join) 闭合图形的连接处效果
先看一个简单的demo:
public class DemoView extends View { Paint paint = new Paint(); Path path =
new Path(); public DemoView(Context context) { this(context,null); } public
DemoView(Context context, @Nullable AttributeSet attrs) { this(context,
attrs,0); } public DemoView(Context context, @Nullable AttributeSet attrs, int
defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void
init(){ paint.setAntiAlias(false); paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10); paint.setColor(Color.parseColor("#ff0000"));
//path在后面进行讲解 path = new Path(); path.moveTo(150, 400); path.lineTo(450, 400);
path.lineTo(300, 150); path.close(); } @Override protected void onDraw(Canvas
canvas) { super.onDraw(canvas); canvas.drawPath(path,paint); } }
效果如图:


下面几个重要属性详细介绍:

###setAlpha(int a) —透明度
paint.setAlpha(100);


###setAntiAlias(boolean aa) —是否抗锯齿
false不抗锯齿
paint.setAntiAlias(false);


true抗锯齿
paint.setAntiAlias(true);


###setStyle(Style style)—设置画笔风格
Style.FILL:实心
Style.FILL_AND_STROKE:同时显示实心和空心
Style.STROKE:空心
paint.setStyle(Paint.Style.STROKE);
效果如图:

paint.setStyle(Paint.Style.FILL);


###setStrokeWidth—空心画笔宽度
setStrokeWidth(int width)


###setStrokeCap(CAP cap)—线段末端效果


###setStrokeJoin(Join join)—闭合图形的连接处效果


###setTextAlign(Paint.Align align)—设置文本对齐


###setTextSize(float testSize)—设置字体的大小
private void init(){ paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#ff0000")); paint.setTextSize(50); } @Override
protected void onDraw(Canvas canvas) { super.onDraw(canvas);
canvas.drawText("自定义View",200,200,paint); }
如图:


###setShader(Shader shader)—设置阴影
Shader本身是一个抽象类,它提供了如下实现类:

BitmapShader: 使用位图平铺的渲染效果.

LinearGradient: 使用线性渐变来填充图形.

RadialGradient: 使用圆形渐变来填充图形.

SweepGradient: 使用角度渐变来填充图形.

ComposeShader: 使用组合渲染效果来填充图形.
private void init() { paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#ff0000")); paint.setTextSize(50); int[]
colors = new int[] { Color.RED, Color.GREEN, Color.BLUE }; Shader shader = new
RadialGradient(100, 100, 80,colors, null, TileMode.REPEAT);
paint.setShader(shader·); } @Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas); canvas.drawText("自定义View", 200, 200, paint); }
如图:


是不是有种艺术字的效果。

###setTextScaleX(float scaleX)—设置缩放倍数
设置水平缩放
paint.setTextScaleX(2);
如图:


###设置字体类型

public static final Typeface DEFAULT; // 默认字体

public static final Typeface DEFAULT_BOLD; //加粗

public static final Typeface SANS_SERIF; //sans serif字体类型

public static final Typeface SERIF; //SERIF字体

public static final Typeface MONOSPACE; //等宽字体
paint.setTypeface(Typeface.DEFAULT_BOLD); //加粗
如图:


<>setUnderlineText(boolean underlineText) —设置下划线
paint.setUnderlineText(true);


<>setMaskFilter(MaskFilter maskfilter)—滤镜的效果

设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等

Android包含了下面几种MaskFilter:
BlurMaskFilter 指定了一个模糊的样式和半径来处理Paint的边缘。
EmbossMaskFilter 指定了光源的方向和环境光强度来添加浮雕效果。
BlurMaskFilter maskFilter = new BlurMaskFilter(10,
BlurMaskFilter.Blur.SOLID); paint.setMaskFilter(maskFilter);
<>

#Path类使用详解
Path类可以预先在View上将N个点连成一条"路径",然后调用Canvas的drawPath(path,paint)即可沿着路径绘制图形。

下面是常用方法:

方法 作用 备注
moveTo 移动起点 移动下一次操作的起点位置
lineTo 连接直线 连接上一个点到当前点之间的直线
setLastPoint 设置终点 重置最后一个点的位置
close 闭合路劲 从最后一个点连接最初的一个点,形成一个闭合区域
addRect 添加矩形 添加矩形到当前Path
addRoundRect 添加圆角矩形 添加圆角矩形到当前Path
addOval 添加椭圆 添加椭圆到当前Path
addCircle 添加圆 添加圆到当前Path
addPah 添加路劲 添加路劲到当前Path
addArc 添加圆弧 添加圆弧到当前Path
arcTo 圆弧 绘制圆弧,注意和addArc的区别
isEmpty 是否为空 判定Path是否为空
isRect 是否为矩形 判定Path是否是一个矩形
set 替换路劲 用新的路劲替换当前路劲的所有内容
offset 偏移路劲 对当前的路劲进行偏移
quadTo 贝塞尔曲线 二次贝塞尔曲线的方法
cubicTo 贝塞尔曲线 三次贝塞尔曲线的方法
rMoveTo,rlineTo,rQuadTo,rCubicTo rXxx方法 不带r的方法是基于原点坐标系(偏移量),带r的基于当前点坐标系(偏移量)
op 布尔操作 对两个Path进行布尔运算(交集,并集)等操作
setFillType 填充模式 设置Path的填充模式
getFillType 填充模式 获取Path的填充
isInverseFillType 是否逆填充 判断是否是逆填充模式
toggleInverseFillType 相反模式 切换相反的填充模式
getFillType 填充模式 获取Path的填充
incReserve 提示方法 提示Path还有多少个点等待加入
computeBounds 计算边界 计算Path的路劲
reset,rewind 重置路劲 清除Path中的内容(reset相当于new Path , rewind 会保留Path的数据结构)
transform 矩阵操作 矩阵变换
由于属性过多,我们分组进行讲解:
先创建画笔:
public DemoView(Context context, @Nullable AttributeSet attrs, int
defStyleAttr) { super(context, attrs, defStyleAttr); paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#ff0000"));
paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(10); }
###第一组:画线段(绝对坐标) XXXTo方法
moveTo , lineTo , setLastPoint , close
我们来看上面绘制的三角形
path.moveTo(150, 400); //起点 (150,400) path.lineTo(450, 400); //移动到(450,400)
path.lineTo(300, 150); //移动到(300,150) path.close(); //回到起点


我们把path.close() 去掉, 看一下效果


###第二组:画线段(相对坐标) rXXXTo方法

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

我们看一下代码就知道什么情况了:
path.moveTo(100, 100); path.LineTo(200, 200);
这里的move和lineTo的坐标都是对于画布左上角(0,0)来说的,是一个绝对坐标。

path.moveTo(100, 100); path.rLineTo(200, 200);
这里的(200,200)是相对于开始点(100,100)来说的,是相对坐标。


###第三组:画贝赛尔曲线
quadTo,cubicTo 二次贝塞尔曲线以及三次贝塞尔曲线
####1.quadTo
//quadTo方法其中 (x1,y1) 为控制点,(x2,y2)为结束点。 public void quadTo(float x1, float y1,
float x2, float y2)


解释:其中quadTo的前两个参数为控制点的坐标,后两个参数为终点坐标,至于起点默认是画布的左上角。这里的p0就是起点,(x1,y1)就是中点P1,(x2,y2)就是末端点P2。
path = new Path(); path.moveTo(150, 400); path.quadTo(200, 200, 400, 400);
效果如图:


####2、cubicTo
//cubicTo方法比quadTo方法多了一个点坐标,那么其中(x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。 public
void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

解释:与quadTo类似,前四个参数表示两个控制点,最后两个参数表示终点。其实,(x1,y1)就是P1,(x2,y2)是P2,(x3,y3)是P3。
path.moveTo(100, 400); path.cubicTo(200, 200, 300, 200, 400, 400);
效果如图:


###第四组:画弧线

arcTo (RectF oval, float startAngle, float sweepAngle)
上面这个方法就是画圆弧,说白了就是先确定一个矩形区域,这个区域就是圆或者椭圆的区域,然后在上面截取一段。
path.moveTo(100, 100); RectF oval = new RectF(100, 100, 200, 200);
path.arcTo(oval, 0, 90);




这里你会发现有一条从起点到圆弧的直线,那么使用下面的方法可以重置起点。

arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
path.moveTo(100, 100); RectF oval = new RectF(100, 100, 200, 200);
path.arcTo(oval, 0, 90,true);


###第五组:添加path(addXXX方法)

addXXX方法则可以让我们直接往Path中添加一些曲线。
比如:

addArc(RectF oval, float startAngle, float sweepAngle)
addCircle(float x, float y, float radius, Path.Direction dir)
addOval(float left, float top, float right, float bottom, Path.Direction dir)
addRect(float left, float top, float right, float bottom, Path.Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx,
float ry, Path.Direction dir)


我们注意到addArc和其他四个方法的区别在于Path.Direction这个参数,因为addArc添加的是一个开放曲线,而其他的方法添加的是闭合曲线,所以Path.Direction就是闭合曲线的方向。

让我们看一下示例:
path.moveTo(100, 100); path.rLineTo(200, 200); RectF oval = new RectF(100,
100, 200, 200); path.addArc(oval, 0, 90);
这是我们上面讲的两个图形 add到了一起。


是不是豁然开朗,那再让我们看一下其他的需要使用Path.Direction这个的效果。
path = new Path(); path.moveTo(100, 100); path.rLineTo(200, 200); RectF oval
= new RectF(100, 100, 300, 300); path.addRect(oval, Path.Direction.CW);


那么上面的例子可能看不出来CW和CCW的太大区别,下面的例子就可以直观的看出来了。
path = new Path(); RectF oval = new RectF(100, 100, 300, 300);
path.addRect(oval, Path.Direction.CW); canvas.drawPath(path,paint);
paint.setTextSize(60); canvas.drawTextOnPath("12345",path,0,0,paint);
Path.Direction只有两个常量值CCW和CW分别表示逆时针方向闭合和顺时针方向闭合。
CW


CCW


###第六组:path的集合运算(op方法)
先看下代码
Path path1 = new Path(); path1.addCircle(120, 120, 100, Path.Direction.CW);
Path path2 = new Path(); path2.addCircle(200, 200, 100, Path.Direction.CW); if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { path1.op(path2,
Path.Op.UNION); //这边使用不同属性效果如下表 } canvas.drawPath(path1, paint);
逻辑名称 类比 说明 示意图
DIFFERENCE 差集 Path1中减去Path2后剩下的部分
REVERSE_DIFFERENCE 差集 Path2中减去Path1后剩下的部分
INTERSECT 交集 Path1与Path2相交的部分
UNION 并集 包含全部Path1和Path2
XOR 异或 包含Path1与Path2但不包括两者相交的部分
###第七组:填充效果(setFillType方法)

参数 解释 效果
WINDING 非零环绕数规则填充
INVERSE_WINDING 和WINDING相反
EVEN_ODD 奇偶规则填充
INVERSE_EVEN_ODD 和EVEN_ODD相反
#PathEffect类使用详解
PathEffect是用来控制绘制轮廓(线条)的方式。

常用PathEffect如下:

方法 作用
CornerPathEffect 可以使用圆角来代替尖锐的角从而对基本图形的形状尖锐的边角进行平滑。
DashPathEffect
可以使用DashPathEffect来创建一个虚线的轮廓(短横线/小圆点),而不是使用实线。你还可以指定任意的虚/实线段的重复模式。
DiscretePathEffect 与DashPathEffect相似,但是添加了随机性。当绘制它的时候,需要指定每一段的长度和与原始路径的偏离度。
PathDashPathEffect 这种效果可以定义一个新的形状(路径)并将其用作原始路径的轮廓标记。
SumPathEffect 顺序地在一条路径中添加两种效果,这样每一种效果都可以应用到原始路径中,而且两种结果可以结合起来。
ComposePathEffect 组合效果,这个类需要两个PathEffect参数来构造一个实例,ComposePathEffect
(PathEffect outerpe,PathEffect
innerpe),表现时,会首先将innerpe表现出来,然后再在innerpe的基础上去增加outerpe的效果。。
看一个demo就知道这几个效果的区别了。
paint = new Paint(); paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4); //创建,并初始化Path path = new Path(); path.moveTo(100,
100); path.rLineTo(90,0); path.rLineTo(-80,50); path.rLineTo(35,-80);
path.rLineTo(45,80); path.close(); //初始化七个颜色 colors = new int[] {
Color.BLACK,Color.BLUE,Color.CYAN,
Color.GREEN,Color.MAGENTA,Color.RED,Color.YELLOW,Color.BLACK }; @Override
protected void onDraw(Canvas canvas) { super.onDraw(canvas); //将背景填充成白色
canvas.drawColor(Color.WHITE); //-------下面开始初始化7中路径的效果 //使用路径效果 effects[0] =
null; //使用CornerPathEffect路径效果 effects[1] = new CornerPathEffect(10);
//初始化DiscretePathEffect effects[2] = new DiscretePathEffect(3.0f,5.0f);
//初始化DashPathEffect effects[3] = new DashPathEffect(new
float[]{20,10,5,10},phase); //初始化PathDashPathEffect Path p = new Path();
p.addRect(0, 0, 8, 8, Path.Direction.CCW); effects[4] = new
PathDashPathEffect(p,12,phase,PathDashPathEffect.Style.ROTATE);
//初始化PathDashPathEffect effects[5] = new
ComposePathEffect(effects[2],effects[4]); effects[6] = new
SumPathEffect(effects[4],effects[3]); //将画布移到8,8处开始绘制 canvas.translate(8, 8);
//依次使用7中不同路径效果,7种不同的颜色来绘制路径 for(int i = 0; i < effects.length; i++) {
paint.setPathEffect(effects[i]); paint.setColor(colors[i]);
canvas.drawPath(path, paint); canvas.translate(0, 60); } //改变phase值,形成动画效果
phase += 1; invalidate(); }


扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~

公众号回复“资料获取”,获取更多干货哦~

有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码