这里我们来学习一下Paint的使用,废话不多说,开始撸码
正文
开始我们先要学习一下Paint的简单使用喽!
-
设置画笔样式
.setStyle(Paint.Style style) Paint.Style.FILL :填充内部 Paint.Style.FILL_AND_STROKE :填充内部和描边 Paint.Style.STROKE :仅描边 注意STROKE、FILL_OR_STROKE与FILL模式下外轮廓的位置会扩大
-
设置画笔宽度
.setStrokeWidth(float width)
-
设置画笔是否抗锯齿
.setAntiAlias(boolean aa)
-
设置线冒样式
.setStrokeCap(Paint.Cap cap) Cap.ROUND(圆形线冒)、Cap.SQUARE(方形线冒)、Paint.Cap.BUTT(无线冒)
-
设置线段连接处样式
.setStrokeJoin(Paint.Join join) Join.MITER(结合处为锐角)、Join.Round(结合处为圆弧)、Join.BEVEL(结合处为直线)
-
设置笔画的倾斜度
.setStrokeMiter(float miter)
-
清空画笔复位
.reset()
-
设置一个外来Paint画笔
.set(Paint src)
-
设置alpha值、颜色、ARGB
.setAlpha(int a) .setColor(int color)
-
获取与设置是否使用抗锯齿功能
.isAntiAlias()
-
设置抗锯齿
setAntiAlias(boolean aa)
-
是否使用图像抖动处理
.isDither()
-
设置图像抖动,会使绘制出来的图片颜色更加平滑和饱满、图像更加清晰
.setDither(boolean dither)
-
设置绘制路径的效果
.setPathEffect(PathEffect effect) CornerPathEffect——圆形拐角效果 DashPathEffect——虚线效果 例 //画同一条线段,偏移值为15 paint.setPathEffect(new DashPathEffect(new float[]{20,10,50,100},15)); intervals[]:表示组成虚线的各个线段的长度;整条虚线就是由intervals[]中这些基本线段循环组成的。比如,我们定义new float[] {20,10};那这个虚线段就是由两段线段组成的,第一个可见的线段长为20,每二个线段不可见,长度为10; phase: 开始绘制的偏移值 ComposePathEffect ComposePathEffect先应用圆角特效,再应用虚线特效 SumPathEffect 将生成的两条特效路径合并
-
设置图形重叠时的处理方式
.setXfermode(Xfermode xfermode)
-
设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果
.setMaskFilter(MaskFilter maskfilter)
-
设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果
.setColorFilter(ColorFilter colorfilter)
-
设置图像效果,使用Shader可以绘制出各种渐变效果
.setShader(Shader shader)
-
在图形下面设置阴影层,产生阴影效果
.setShadowLayer(float radius ,float dx,float dy,int color)
radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色 -
获取字符行间距
.getFontSpacing()
-
设置和获取字符间距
.setLetterSpacing(float letterSpacing) .getLetterSpacing()
-
是否有下划线和设置下划线
.isUnderlineText() .setUnderlineText(boolean underlineText)
-
获取与设置是否有文本删除线
.isStrikeThruText() .setStrikeThruText(boolean strikeThruText)
-
获取与设置文字大小
.getTextSize() .setTextSize(float textSize) 注意:Paint.setTextSize传入的单位是px,TextView.setTextSize传入的单位是sp
-
获取与设置字体类型
.getTypeface() .setTypeface(Typeface typeface) Android默认有四种字体样式:BOLD(加粗)、BOLD_ITALIC(加粗并倾斜)、ITALIC(倾斜)、NORMAL(正常),我们也可以通过Typeface类来自定义个性化字体。
-
获取与设置文字倾斜
.getTextSkewX() .setTextSkewX(float skewX) 官方推荐值为-0.25,值为负则右倾,为正则左倾,默认值为0。
-
获取与设置文本对齐方式
.getTextAlign() .setTextAlign(Paint.Align align)
-
设置亚像素,亚像素就是把两个相邻的两个像素之间的距离再细分,再插入一些像素,这些通过程序加入的像素就是亚像素。在两个像素间插入的像素个数是通过程序计算出来的,一般是插入两个、三个或四个。所以打开亚像素显示,是可以在增强文本显示清晰度的,但由于插入亚像素是通过程序计算而来的,所以会耗费一定的计算机性能
.setSubpixelText(boolean subpixelText)
-
动态折断或生成一行字符串
breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth)
-
获取文本的宽高,通过bounds的Rect拿到整型
void getTextBounds(char[] text, int index, int count, Rect bounds) void getTextBounds(String text, int start, int end, Rect bounds)
-
粗略获取文本的宽度
float measureText(String text) float measureText(CharSequence text, int start, int end) float measureText(String text, int start, int end) float measureText(char[] text, int index, int count)
-
精确计算文字宽度
int getTextWidths(String text, int start, int end, float[] widths) int getTextWidths(String text, float[] widths) int getTextWidths(CharSequence text, int start, int end, float[] widths) int getTextWidths(char[] text, int index, int count, float[] widths)
另外就是文字位置的解析,先了解一下FontMetrics的top,ascent,desent, bottom的属性
top = top线的y坐标 - baseline线的y坐标
bottom = bottom线的y坐标 - baseline线的y坐标
ascent = ascent线的y坐标 - baseline线的y坐标
desent = desent线的y坐标 - baseline线的y坐标
看图就能计算出下面的结论
baseline = center +(FontMetrics.bottom - FontMetrics.top)/2 - FontMetrics.bottom
知道这些我们能做什么,下图就可以搞出来
分析图
边上的曲线可以使用二级贝塞尔曲线加上半圆来绘制,整体是一个正五边形
部分代码:
private void drawSmallCircleList(Canvas canvas, PointF node, POSITION position) {
Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(Color.parseColor("#888888"));
circlePaint.setStrokeWidth(5);
circlePaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(node.x, node.y, DEFAULT_CIRCLE_R * 1.0f / 3, circlePaint);
PointF beforePoint = node;
for (int i = 0; i < 5; i++) {
float lineDistance = 1.0f / (i + 3) * DEFAULT_CIRCLE_R + DEFAULT_SMALL_CIRCLE_SPACE + 1.0f / (i + 4) * DEFAULT_CIRCLE_R;
PointF circlePoint = null;
if (position == POSITION.LT) { //左上
circlePoint = new PointF(beforePoint.x + lineDistance * 0.5f * (float) Math.pow(3, 0.5), beforePoint.y + lineDistance * 0.5f);
} else if (position == POSITION.LB) {//左下
circlePoint = new PointF(beforePoint.x + lineDistance * 0.5f, beforePoint.y - lineDistance * 0.5f * (float) Math.pow(3, 0.5));
} else if (position == POSITION.RT) {//右上
circlePoint = new PointF(beforePoint.x - lineDistance * 0.5f * (float) Math.pow(3, 0.5), beforePoint.y + lineDistance * 0.5f);
} else {//右下
circlePoint = new PointF(beforePoint.x - lineDistance * 0.5f, beforePoint.y - lineDistance * 0.5f * (float) Math.pow(3, 0.5));
}
canvas.drawCircle(circlePoint.x, circlePoint.y, DEFAULT_CIRCLE_R * 1.0f / (i + 4), circlePaint);//绘制圆形
beforePoint = circlePoint;
}
}