我们在自定义View的时候总是会用到Paint画笔对象和Canvas对象,我是这么理解的,你要画一个自定义View就必须要有水彩笔和你的A4纸(当然我只是这么一说,也可以使任何纸),水彩笔就相当于Paint画笔对象,可以设置它的颜色,粗细,想要画的字的大小,形状以及一些样式,接下来,我们来看一下这个画笔对象是什么以及怎么使用.
Paint是什么?
首先来看一下官方解释:
The Paint class holds the style and color information about how to draw geometries, text and bitmaps.
用我粗略的英语水平翻译一下,Paint对象保存了样式,颜色信息以及如何画几何图形,写文字和画图片的信息.就可以简单的理解为我上面开篇所说的,就理解成你画画时用的水彩笔就可以了,它有粗细颜色等信息,Paint就是用来保存这些信息.
来看一下Paint的构造函数

总共有三个,我们一一来看一下:
1.创建一个空的Paint,里面什么信息都没有保存
2.根据特殊的flags创建Paint(比如扛锯齿等等),下面介绍怎么用时会说到,莫急
3.创建一个Paint,里面有你创建的上一个Paint对象的一下信息,用来避免重复赋值以及节省代码时间
在来看一下对于Paint来说比较重要的它的6个枚举内部类(可以理解为只有五个)

1.Align 文字的对齐方式
2.Cap 线帽,可能你在此处不怎么理解,下面看效果图就一目了然
3.FontMetrics 字体矩阵,用来控制文字的矩阵变换,里面包含了一些文字的参数变量
4.FontMetricsInt 其实和FontMetrics是差不多的,只不过精度改为了int而已,方法什么的都差不多
5.Join 我理解为线段折弯处的变现,看下面效果也会一目了然
6.Style 样式,这个简单,设置画笔的样式
好了,啰嗦完了,现在可以进入主题了
Paint怎么用?
使用Paint,就意味着要初始化,一般分为这几个步骤,在前几个博客也有讲过
1.继承View
2.重写构造函数
3.初始化Paint对象
4.重写onMeasure(这里我们不重写,以后我们会经常用到)
5.重写onDraw函数
6.(不要忘了在xml文件中运用,需要用包名,不然肯定是没有效果的,是中只有hello world,小错误没必要犯)
我们一般都会选择在构造函数中初始化画笔等的对象,这样每次创建对象的时候都能初始化,而且只有一次,后续需要修改也可以.在onDraw函数中,会有一个画布Canvas对象的使用,如果你不懂,那就请看我的这篇文章--->
我们就从他的6个内部枚举开始讲起,从最简单的开始
Style
public enum Style {
FILL (0), //填充内部
STROKE (1), //描边
FILL_AND_STROKE (2); //描边和填充内部
}这里第一个给出全部的代码,之后修改的代码就是在两个地方,为了避免重复,你们自己改一下就行了
STROKE
直接上代码,效果跟下面对比很明显
public class MyPaintView extends View {
private Paint mPaint;
public MyPaintView(Context context) {
this(context,null);
}
//这个都构造函数是必须的,我是采用调用下面那个的方式
public MyPaintView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyPaintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initControl(); //初始化画笔
}
private void initControl() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE); //设置成描边的效果,也就是画边框
mPaint.setStrokeWidth(10); //设置描边的宽度粗细
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2); //把画布移动到中间
canvas.drawCircle(0,0,200,mPaint); //画圆
}
}效果图

额,这图片怎么看起来有点不舒服,总感觉不够圆,毛毛草草的,是吧,(不信你就放大了看,会很明显的),其实圆也是无数条线段画出来的,所以这就会出现一种齿轮的感觉,我们要去掉这种状态就叫做抗锯齿,既然我们都看出来了,那安卓早就想到了,下面我们来解决他.come on~
private void initControl() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setAntiAlias(true); //设置抗锯齿
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,200,mPaint);
}效果图

现在图片看上去是不是舒服多了~圆滑,顺溜,舒服~
就是这样,你没看错,这里就多了一句话,上面用注释标出来了,现在来讲下上面说的根据构造函数来创建Paint对象的方法.
其实flags就是在Paint类下的一些常量,你可以在源码中看到,这里我就介绍一个,其他的类似,自己琢磨一下很容易就懂啦~
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //创建对象时传入flag
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
// mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,200,mPaint);
}这里的效果和上面的那个抗锯齿的效果是一样的.就不给效果图了,自己尝试吧~加油宝贝~
除此之外,下面还有很多这样的常量,也可以使用setXXX的方式设置进去,看你自己喜欢咯~

这里有设置图像是否抖动等等的方式,我是认为现在我也不是很了解图像这方面的知识,有点像是PS的内容,(说实话我也不知道是不是,如果你们知道,请你们告诉我,学习是我喜欢做的事情~),现在暂时放一放,日后等我研读完启舰大神的《Android自定义控件入门与实战》再来跟你们回头狠狠分析一波~ok,next~
FILL
直接看代码和效果图吧
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL); //改为FILL样式
mPaint.setStrokeWidth(10);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,200,mPaint);
}效果图

效果很明显,就不多说什么了,自己体会~这里顺带说一下,我没有设置画笔的颜色,默认就是黑色的,下面我会设置成其他的颜色.
FILL_AND_STROKE
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED); //设置画笔颜色为红色
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); //描边和填充内部
mPaint.setStrokeWidth(10);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,200,mPaint);
}效果图

这里看不出来有没有描边,和填充的看上去没什么区别,下面,我们来区别一下,我们把三种效果合在一起看就很明显了.
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(30); //边宽度
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,-300,100,mPaint); //STROKE样式
mPaint.setStyle(Paint.Style.FILL); //FILL样式
canvas.drawCircle(0,0,100,mPaint);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); //FILL_AND_STROKE
canvas.drawCircle(0,300,100,mPaint);
mPaint.setColor(Color.BLACK); //设置画笔颜色
mPaint.setStrokeWidth(3); //设置画笔为黑色
canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint); //辅助线
canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint); //辅助线
} 效果图

我们画的是半径为100的圆,我故意把边的粗细改为30,让效果更佳明显,通过辅助线,可以看的很明显了吧~我就不多说什么了,下面我在演示Cap和Join的时候也会直接上对比图,这里是带你慢慢理解,最后还是要放在一起对比,如果你想一一尝试的话自己去尝试,很简单,我就直接给对比图了~请理解,不懂的话联系我~
Cap(线帽)
直接上代码看效果吧~讲不清楚~so sorry~
还是一样,先看一下源码,然后我就直接展示所有了,对比着学更容易些,我是这么觉得,你要是不理解的话自行分开来画一下
源码:(总共三个常量)
public enum Cap {
BUTT (0), //这里都是我理解的,没有线帽
ROUND (1), //圆的
SQUARE (2); //方的
}效果代码:
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(100);
mPaint.setStrokeCap(Paint.Cap.SQUARE); //SQUARE线帽
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawLine(-100,-200,100,-200,mPaint); //画直线
mPaint.setStrokeCap(Paint.Cap.ROUND); //ROUND线帽
canvas.drawLine(-100,0,100,0,mPaint);
mPaint.setStrokeCap(Paint.Cap.BUTT); //BUTT线帽
canvas.drawLine(-100,200,100,200,mPaint);
mPaint.setColor(Color.BLACK); //以下是辅助线
mPaint.setStrokeWidth(3);
canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint);
canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint);
}效果图

这里我故意设置描边的宽度为100,为了效果,说白了就是给线条带了顶帽子,Cap的三个常量就代表帽子的样式而已~
Join
这个我也不知道如何解释,我能解释的就是线条折弯处的圆角还是其他样式,直接看效果吧,也是非常明显的
还是一样,源码:(也是3个)
public enum Join {
MITER (0),
ROUND (1),
BEVEL (2);
}效果代码:(因为是线段折弯处的效果,所以这里我画一个类似字码Z来让你看清楚折弯处的表现)
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(30);
mPaint.setStrokeJoin(Paint.Join.BEVEL); //折弯处表现为BEVEL
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
Path path = new Path();
path.moveTo(-100,-100);
path.lineTo(100,-100);
path.lineTo(-100,100);
path.lineTo(100,100);
canvas.drawPath(path,mPaint);
mPaint.setStrokeJoin(Paint.Join.MITER); //折弯处表现为MITER
path.reset();
path.moveTo(-100,-400);
path.lineTo(100,-400);
path.lineTo(-100,-200);
path.lineTo(100,-200);
canvas.drawPath(path,mPaint);
mPaint.setStrokeJoin(Paint.Join.ROUND); //折弯处表现为ROUND
path.reset();
path.moveTo(-100,200);
path.lineTo(100,200);
path.lineTo(-100,400);
path.lineTo(100,400);
canvas.drawPath(path,mPaint);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint);
canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint);
}效果图

效果一眼就全知道了,不多说了,至于不明白Path的使用的同学,可以看我的文章----> 自定义View之Path的使用
在这里,首先恭喜你,关于线段和几何图形的内部枚举类,你已经学习完了,现在我们来看文字的内部枚举类吧,总共有三个,但我们只要说两个,还有个无非就是精度上的差别~小意思嘛~
一个简单,一个有点难度,那让我们先来看简单的
Align
学过html的你一下子就知道什么意思了吧,文字对齐方式嘛~这里就不给源码了,总共三个left,right和center
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setTextAlign(Paint.Align.CENTER); //居中
mPaint.setTextSize(30); //设置字体大小
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawText("我是一个热爱学习的好孩子",0,0,mPaint);
mPaint.setTextAlign(Paint.Align.LEFT); //靠左对齐
canvas.drawText("我是一个热爱学习的好孩子",0,-300,mPaint);
mPaint.setTextAlign(Paint.Align.RIGHT); //靠右对齐
canvas.drawText("我是一个热爱学习的好孩子",0,300,mPaint);
mPaint.setColor(Color.BLACK); //下面是辅助线
canvas.drawLine(0,-getHeight()/2,0,getHeight()/2,mPaint);
canvas.drawLine(-getWidth()/2,0,getWidth()/2,0,mPaint);
canvas.drawLine(-getWidth()/2,-300,getWidth()/2,-300,mPaint);
canvas.drawLine(-getWidth()/2,300,getWidth()/2,300,mPaint);
}效果图

效果很明显,咦~你为什么要画辅助线呀,这个辅助线有意思吗,你不是在浪费时间吗?不,不是的,我是想引出下一个要将的FontMatrics的用法,你有没有发现虽然文字在水平的方向是对齐的,但是文字在垂直方向上,始终画在我的辅助线的上方,细心的你发现了吗?那么你就说了,既然水平方向有这样的方法,那垂直方向就肯定有咯,在这里我很遗憾的告诉你,并没有这样的方法,那怎么做呢?不要急嘛,马上就手把手教会你.
FontMatrics
首先来看下源码的注释,凑合着还能翻译一下
/**
* Class that describes the various metrics for a font at a given text size.
* Remember, Y values increase going down, so those values will be positive,
* and values that measure distances going up will be negative. This class
* is returned by getFontMetrics().
*/
public static class FontMetrics {
/**
* The maximum distance above the baseline for the tallest glyph in
* the font at a given text size.
*/
public float top;
/**
* The recommended distance above the baseline for singled spaced text.
*/
public float ascent;
/**
* The recommended distance below the baseline for singled spaced text.
*/
public float descent;
/**
* The maximum distance below the baseline for the lowest glyph in
* the font at a given text size.
*/
public float bottom;
/**
* The recommended additional space to add between lines of text.
*/
public float leading;
}FontMetrics这个类是用来记录已经给出的字体的矩阵的.你要记住,在y轴往下y值会增加,移动的话就是正数,往上,y值会减小,也就是说移动的话这个数是负数,和数学上的相反,比如y-5表示想上移动5,y+5表示向下移5.
top : 在基线以上的最大距离,为什么说会有最大距离呢,你要知道,世界上有n多种文字,每种文字的高度和书写格式是不一样的,所以会存在最大值
ascent : 建议的在基线之上的距离,为负数(英文为上坡的意思),我觉得就是实际的文字在基线之上的距离
descent : 建议的在基线之下的距离,为正数(英文为下坡的意思),我觉得就是实际的文字在基线之下的距离
特别记忆法 : 上坡y值跟数学相反,减小为负,下坡则相反,so easy~~~
bottom : 在基线之下最大的距离,原因类似于top
leading : 这个就简单了,行间距
其实啊,我们的drawText方法是根据基线来写的文字,那么这个基线(baseLine)又是什么呢?现在我告诉你一个公式:
baseLine = 文本中线 - descent ; 我们如果要让文字看上去居中,就必须要算出baseLine的位置才行.
我使用的记忆方法是把画布移动中间,然后以中心点为原点,就中间有个x轴和y轴,(0,0)就好考虑,先算出基于原点的baseLine,然后进行移动不就完事了,不然计算太麻烦了,如果你的数学好,那可以,不然我觉得我的这个方法记忆比较好~
首先我们来画一个图来更好的理解这几个参数的意思,leading就不说了,word中就有,自己去尝试一下吧~来吧,激动人心的时刻~
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(100);
mPaint.setStrokeWidth(2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth() / 2, getHeight() / 2);
String text = "xyz";
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
mPaint.setColor(Color.BLACK);
canvas.drawLine(-getWidth() / 2, //画top线
fontMetrics.top,
getWidth() / 2,
fontMetrics.top, mPaint);
mPaint.setColor(Color.RED);
canvas.drawLine(-getWidth() / 2, //画ascent线
fontMetrics.ascent,
getWidth() / 2,
fontMetrics.ascent, mPaint);
mPaint.setColor(Color.parseColor("#00ff00"));
canvas.drawLine(-getWidth() / 2, //画基线
0,
getWidth() / 2,
0, mPaint);
mPaint.setColor(Color.parseColor("#f89e6f"));
canvas.drawLine(-getWidth() / 2, //画descent线
fontMetrics.descent,
getWidth() / 2,
fontMetrics.descent, mPaint);
mPaint.setColor(Color.RED);
canvas.drawLine(-getWidth() / 2, //画bottom线
fontMetrics.bottom,
getWidth() / 2,
fontMetrics.bottom, mPaint);
canvas.drawText(text, 0, 0, mPaint);
}效果图

其实,我们是不需要关注这么多线的,我们要知道它是怎么绘制的,重点在于三根线,我们并不需要很关注最大的top和bottom
baseLine : 基线,也就是你在drawText的时候写入的坐标
ascent(在基线之上的距离) 还有 descent(在基线之下的距离) ,这两个我就在图中表示出来,如下:

图上就已经表明的很清楚,"{"就是指ascent和baseLine的距离,"}"就是指baseLine和descent之间的距离,可以用绝对值表示
那么问题来了,说来说去,知道这些有什么用呢?这个问题好,加下来我们可以用上面学到的知识来写字写在垂直据中的位置上,come on~
Step 1 : 既然要画在中间,就需要知道中线,文字的中线计算出baseLine的距离,我这里是相对于原点计算的,其他的话只要一动一下就可以了,很方便~原先的中线要一动到baseline的位置才能居中显示
Step 2 : 根据baseLine来drawText,直接上代码和效果图
公式: 移动的距离 = 中线(这里不能像其他博客所说的中线,而是text文本的高度的一半) - descent(这个是正数)
多打几遍你就知道了.
先来看代码,我会给出辅助线对比居中和不居中的形式:
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(100);
mPaint.setStrokeWidth(2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth() / 2, getHeight() / 2); //移动画布
String text = "abp"; //要写的内容
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics(); //获取FontMetrics
Rect rect = new Rect(); //用来测量文本框大小,计算高度一半
mPaint.getTextBounds(text, 0, text.length(), rect); //获取文字矩形框大小
int baseX = -200; //baseLine坐标
int baseY = 0;
int textHeight = rect.height(); //获取文字高度
canvas.drawText(text, baseX, baseY, mPaint); //写字,没有居中的
int moveDistance = (int) (textHeight / 2 - fontMetrics.descent); //计算中线下移距离
canvas.drawText(text, -baseX, baseY + moveDistance, mPaint); //写字居中
mPaint.setColor(Color.BLACK); //辅助线
canvas.drawLine(-getWidth() / 2, 0, getWidth() / 2, 0, mPaint);
}效果图

额额,写到上面,我保存了草稿,然后之后回来看,突然发现好像没有讲的很清楚,于是盯着上面这图看了半天,还是不知道怎么解释,突然我把英文字母写在了本子上,也不知道怎么,盯着看了半小时之后,突然怎么想的,我想到了小时候练英文字符的本子,然后豁然开朗.看到这里的你是否也有一种朦胧的感觉,没有看懂?半知半解?没关系,下面一张图保管你明白~

小时候写英文字母的格子总知道吧,就是这样子的,假设他们的行间距都是一样的,注意最上面的那条不是ascent,不信你可以用ascent - descent来算一算是不是和rect.height()一样,很遗憾的告诉你不是的,很明显,我们需要把center下移到baseLine的地方就可以了,那么一看就知道,需要下移的距离公式 distance = text的高度(rect.height()) - descent ,生活处处有惊喜,哈哈哈,至少我解决了这个问题是很开心的!现在彻底明白了是怎么回事了吧,这里我试了一下descent和bottom几乎都是重合的,有时间再回头好好研究一下!
到此为止,Paint的几个内部枚举类就还剩下一个FontMatricsInt,只是精度上和FontMatrics有区别,别的没有大的区别,好了~本篇博客的内容你已经学的差不多了,最后说一些方法,我觉得最重要的都在上面了.
api中Paint的一些方法归类讲解
第1组:字体的测量方法
public float measureText(char[] text, int index, int count)
public float measureText(String text, int start, int end)
public float measureText(String text)
public float measureText(CharSequence text, int start, int end)
用来测量字体的宽度,都是重载的方法,三个参数的无非就是让你选择测量的字符格式而已,没有后两个参数的就是全部测量
public int breakText(char[] text, int index, int count,
float maxWidth, float[] measuredWidth)
public int breakText(CharSequence text, int start, int end,
boolean measureForwards,
float maxWidth, float[] measuredWidth)
public int breakText(String text, boolean measureForwards,
float maxWidth, float[] measuredWidth)
从名字就可以看出来,这是一个break(阻断)测量的方法,给出一个字符串,可选择测量字符串的长度,measureForward参数的意思就是是否向前测量,测量的结果保存在float数组中,如果超过设置的maxWidth,就不再进行测量,很简单~自己去尝试吧~
public int getTextWidths(char[] text, int index, int count,
float[] widths)
public int getTextWidths(CharSequence text, int start, int end,
float[] widths)
public int getTextWidths(String text, int start, int end, float[] widths)
public int getTextWidths(String text, float[] widths)
获取文本的宽度,,测量的结果保存在float数组中,也就是最后一个参数中,看参数名也就全知道了,很简洁
这里你会发现measureText好像也是测量字体的宽度,再打印出来看一下,measureText的值总是比getTextWidth要大
这是因为measureText是没有显示之前原始的View的大小,getTextWidths是显示出来后调用的,所以前者总是比后者大,不是其他博客所说的精确测量和非精确测量!在api中也说了getTextWidths是获取当前的text的宽度,也就是显示的,不是原本的View(或者说rect的宽度),懂了吗?(记忆,要有原本的显示的框才能显示呀,预留给它的空间总要比实际使用的大一些才行吧,哈哈~)
public void getTextPath(char[] text, int index, int count,
float x, float y, Path path)
public void getTextPath(String text, int start, int end,
float x, float y, Path path)
这个就是把你文字绘制的路径保存到最后一个参数Path中,一般都传入空,上面的float数组也是传入空的就可以
public void getTextBounds(String text, int start, int end, Rect bounds)
public void getTextBounds(CharSequence text, int start, int end, Rect bounds)
public void getTextBounds(char[] text, int index, int count, Rect bounds)
获取text(文本)的大小,text其实也是在一个Rect中绘制的,如果你对Rect不熟悉,可以看我写的文章,这里就不多说了.也是传入空的Rect对象.就能获取到文本框的大小,在使用Canvas画图画和写字的时候很有用,需要计算的,可以看我写的自定义View之Canvas的使用,在里面我画的自定义时钟就用到了,虽然我故意把它写了几个字上去,但是锻炼是很好的~
第2组
set(Paint src)和reset()
1.set() 把参数Paint中的画笔属性传给调用的Paint
2.reset() 重置画笔属性
第3组
setXXX方法,想简单的一眼就能看明白的(setARGB,setAlpha)这种的我就不多说了,浪费篇幅
1.setAntiAlias(boolean aa) 设置抗锯齿,以上说过了,不多介绍
2.setColorFilter(ColorFilter filter) 设置颜色过滤器,然后我也不知道他是怎么用,应该也不会经常用到~
3.setDither(boolean dither) 设置图像是否抖动,自己百度了解一下
4.setFlags(int flags) 设置flags,其实就是跟new Paint参入构造器中的flags是一个道理的
5.setShadowLayer(float radius, float dx, float dy, int shadowColor) 设置阴影
radius是阴影角度,dx为阴影x轴移动距离,dy为阴影y轴移动距离,shadowColor是阴影颜色
下面来看一下效果
private void initControl() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(80);
mPaint.setStrokeWidth(2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth() / 2, getHeight() / 2);
String text = "abp";
canvas.drawText(text,0,-200,mPaint);
mPaint.setShadowLayer(10,5,5,R.color.colorAccent);
canvas.drawText(text,0,200,mPaint);
}效果图

怎么样,是不是下面的abp看起来有一种立体的感觉,就是这么神奇~android真好玩~
6.setStrikeThruText(boolean strikeThruText) 设置删除线,在构造函数中也可传入对应的flags
7.setTextLocale(Locale locale) 设置text文本的当地语言
8.setTextScaleX(float scaleX) , setTextSkewX(float skewX) 设置text的缩放和错切变换(倾斜)
9.setTypeface(Typeface typeface) 设置字体样式,在TypeFace中有常量来描述,这里就不说了,自己去看
10.setXfermode(Xfermode xfermode) 设置重叠时候的样式,在里面输入Mode类中有18个,自己一一去尝试吧,给点挑战,我就不示范了.
最后两组
这两组就是isXXX和getXXX,这里我就不多说了,都很简单,判断true还是false,get到一些东西,和setXXX基本都是对应的,自行查看api就能搞懂了~
最后,感谢大家的观看,谢谢大家,请期待我的下一篇文章,如有意见,欢迎来稿1012351395@qq.com,新手写博客,希望大家多多给评论,多多给我提意见,我会改进,好好写博客,分享技术给每一个需要的人,我们都是能成大事的人~再见啦~