Paint的基础用法
学习android自定义View总是少不了事件分发,Event ,Scroller,Canvas,Paint ,ViewDragHelper,Path,PathMeasure等等,今天先来弄一下基本的Paint的用法
基础介绍
Paint顾名思意,是android的画笔,我们需要画的绝大部分的东西都是需要Paint来完成的,Canvas负责写文字,drawText,但是Paint负责所画文字的颜色,大小,字体等,Canvas负责drawLine,Paint负责线得颜色等等,不多说直接撸码。
先创建个Paint对象,
mPaint = new Paint();
mPaint.setColor(Color.YELLOW); 设置画笔的颜色,
mPaint.setAntiAlias(true);设置抗锯齿,可能会影响性
mPaint.setDither(true);//防抖动
mPaint.setStyle(Paint.Style.STROKE);//描边
mPaint.setStyle(Paint.Style.FILL);//填充
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//描边加上填充设置画笔的样式
mPaint.setStrokeWidth(1);设置画笔的笔尖的宽度
mPaint.setStrokeCap((Cap cap);设置画笔的线帽,线帽是什么意思呢,线帽就是画笔的帽子。
代码如下:
Path path = new Path();
path.reset();
path.moveTo(100,100);
path.lineTo(600,100);
mPaint.setStrokeWidth(30);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeCap(Paint.Cap.BUTT);//没有笔帽
canvas.drawPath(path,mPaint);
path.reset();
path.moveTo(100,160);
path.lineTo(600,160);
mPaint.setStrokeCap(Paint.Cap.ROUND);//圆角的笔帽
canvas.drawPath(path,mPaint);
path.reset();
path.moveTo(100,220);
path.lineTo(600,220);
mPaint.setStrokeCap(Paint.Cap.SQUARE);//方形的笔帽
canvas.drawPath(path,mPaint);
由图片可得下面的两条线段都比上面没有线帽的线断多出来一段。这就是为Paint添加Cap,线帽产生的作用。
mPaint.setStrokeJoin(Join join);//设置画笔在处理两条线的交叉处如何处理。
上代码:
mPaint.setStrokeWidth(30);
mPaint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.reset();
path.moveTo(40, 40);
path.lineTo(160, 40);
path.lineTo(40, 160);
mPaint.setStrokeJoin(Paint.Join.BEVEL);//直线
canvas.drawPath(path, mPaint);
path.reset();
path.moveTo(40, 200);
path.lineTo(160, 200);
path.lineTo(40, 360);
mPaint.setStrokeJoin(Paint.Join.MITER);//锐角
canvas.drawPath(path, mPaint);
path.reset();
path.moveTo(40, 400);
path.lineTo(160, 400);
path.lineTo(40, 560);
mPaint.setStrokeJoin(Paint.Join.ROUND);//圆弧
canvas.drawPath(path, mPaint);
测量文字
来点有意思的,
breakText(harSequence text, int start, int end,boolean measureForwards,float maxWidth,float [] measuredWidth)
text: 是我们需要测量的文本
start: 测量文本的的字符串的开始的位置
end: 测量文本的字符串结束的位置
measureForwards: 表示测量的方向,如果是true表示是从start开始测量,如果为false代表是从end开始测量
maxWidth: 这个属性比较关键,这是我们先预估我们测量的这段文本的最大宽度是多少,如果在测量的过程中,大于这个设置的最大的宽度,那么这个时候我们就停止测量。
measuredWidth: 如果传入的measuredWidth不为null,那么测量的结果就存储在这个数组里面。
这个函数的返回值是测量的字符串的length
代码如下:
//计算指定长度的字符串(字符长度、字符个数、显示的时候真实的长度)
String str = "this is a Test 中文";
float measuredWidth[] = new float[1];
int length = mPaint.breakText(str,true,800,measuredWidth);
Log.e("TAG","mPaint.breakText() first --- length:"+length +" , measuredWidth :"+measuredWidth[0]);
length = mPaint.breakText(str,0,str.length() -10,true,800,measuredWidth);
Log.e("TAG","mPaint.breakText() second --- length:"+length +" , measuredWidth :"+measuredWidth[0]);
再来:我们继续看看还有哪些可以测量文字
measureText(CharSequence text,int start,int end);
text: 测量的文本
start: 测量的文本的起始位置
end: 测量的文本的结束的位置
上代码:
float measureWidth = mPaint.measureText(str);
Log.e("TAG","mPaint.measureText() first: "+measureWidth);
measureWidth = mPaint.measureText(str,0,str.length() - 10);
Log.e("TAG","mPaint.measureText() second: "+measureWidth);
继续来:再看看
getTextBounds (String text, int start, int end,Rect bounds)
bounds: 这个函数的返回值为void,我们传入的我们定义的bounds,然后这个方法执行完成后,我们就可以在这个bounds里面取得包容下这个文本所需要的最小的矩形。
上代码:
//Rect bounds获取文本的矩形区域(宽高)
Rect rect = new Rect();
mPaint.getTextBounds(str,0,str.length(),rect);
Log.e("TAG","mPaint.getTextBounds() first-- top:"+rect.top+" ,left "+rect.left+ " ,right"+rect.right+" ,bottom:"+rect.bottom);
mPaint.getTextBounds(str,0,str.length()-10,rect);
Log.e("TAG","mPaint.getTextBounds() second-- top:"+rect.top+" ,left "+rect.left+ " ,right"+rect.right+" ,bottom:"+rect.bottom);
好了测量文本的就暂时到这了,当然还有其他的API,我就不介绍了。
FontMetrics
FontMetrics这个类里面只有五个参数,分别是偷top,ascent,desent,bottom,
leading.下面的这张图一斤想看戏的说明了这五个参数的意义,再提一点,我们获取到的
这五个值全是基于baseLine这一条基准线得到的值,所以,baseLine就是坐标原点。
好,我们直接来写一段文字来看看
//画一段文本
canvas.drawText(str,0,0,mPaint);
好了不多说话,直接没画出来什么鬼?原来我们写文字是基于BaseLine来写的,这个时候
BaseLine是0,0这个原点,所以我们写的文字直接出现在了上面,那么我们把BaseLine
下移看看会出现吗?
canvas.drawText(str,0,100,mPaint);
那么我们能解决什么问题呢,来个最普遍的例子,给你一条线,要求你画出的文字是让这条
线位于你所写的文字的中间。就是我们已知centerLine,top,ascent,descent,
bottom,求出BaseLine。
我们已经知道top和bottom,还知道descent,因为我们所知的中线是位于top和bottom
中间的,那么我们可得, (metrics.bottom - metrics.top) / 2 是距离的一半,
那么我们减去底部的距离,就是中间线到baseLine的距离,所以:
baseLineY = (metrics.bottom - metrics.top) / 2 - metrics.bottom + centerY;
那么看一下运行结果
好了,第一篇博客先到这里吧,后面会继续介绍ColorFilter和Shader,Canvas,Path,PathMeasure,事件分发,Scroller等自定义View相关的。。。。