android 画笔设置参数,Android画笔Paint和FontMetrics
有关自定义控件的许多内容,一直都想抽时间梳理一下,当然了梳理的内容不会很深,都是一些比较常用的类或者方法,主要是为了后续用到时方便查阅与参考。
本文主要整理的是Paint的一些基本使用方法和技巧,其中涉及到文字绘制的,涉及绘制文字时需要知道基线的坐标与View的坐标参考点是不同的,需要知道坐标之间的转换方式。另外需要知道有哪些方式可以测量已经绘制的文字所占的宽度,包括可以精确测量的方式,也有相对粗略的方式。
Paint常用方法
Paint在自定义控件中是一个比较常用的类,主要保存了颜色样式等绘制信息,通过一些属性指定如何绘制文字、图形。
如下是Paint的一些常用方法。
setARGB(int a,int r,int g,int b);
设置绘制的颜色,a代表透明度,r,g,b代表颜色值。
setAlpha(int a);
设置绘制图形的透明度,取值范围是[0-255],数值越小,越透明,颜色上表现越淡。
setColor(int color);
设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。
setAntiAlias(boolean aa);
设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
setDither(boolean dither);
设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰,但是会损失性能。
setStyle(Paint.Style style);
设置画笔的样式,为FILL填充,FILL_AND_STROKE填充和描边,或STROKE描边。
setStrokeCap(Paint.Cap cap);
当画笔样式为STROKE或FILL_AND_STROKE时,设置笔刷的图形样式,如圆形样式Cap.ROUND,方形样式Cap.SQUARE 或者不设置Cap.BUTT。
setSrokeJoin(Paint.Join join);
设置绘制时各图形交汇处的结合方式,如Join.MITER锐角、Join.ROUND圆弧、Join.BEVEL直线。
setStrokeWidth(float width);
当画笔样式为STROKE或FILL_AND_STROKE时,设置笔刷的粗细度。
setXfermode(Xfermode xfermode);
设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果。
setShader(Shader shader);
设置图像效果,使用Shader可以绘制出各种渐变效果。
setColorFilter(ColorFilter colorfilter);
设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果。
setShadowLayer(float radius ,float dx,float dy,int color);
在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色。
setTextAlign(Paint.Align align);
设置绘制文字的对齐方向。
setTextScaleX(float scaleX);
设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果。
setTextSize(float textSize);
设置绘制文字的字号大小。
setTextSkewX(float skewX);
设置斜体文字,skewX为倾斜弧度,默认0,官方推荐的-0.25f是斜体。
setTypeface(Typeface typeface);
设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等。
setUnderlineText(boolean underlineText);
设置带有下划线的文字效果。
setStrikeThruText(boolean strikeThruText);
设置带有删除线的效果。
setSubpixelText(boolean subpixelText);
设置该项为true,将有助于文本在LCD屏幕上的显示效果。
部分示例代码演示如下:
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(50);
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);//填充
canvas.drawCircle(200, 200, 100, paint);
paint.setStyle(Paint.Style.STROKE);//描边
canvas.drawCircle(500, 200, 100, paint);
paint.setStyle(Paint.Style.FILL_AND_STROKE);//填充和描边
canvas.drawCircle(800, 200, 100, paint);
paint.setStrokeCap(Paint.Cap.BUTT);//没有
canvas.drawLine(100, 400, 900, 400, paint);
paint.setStrokeCap(Paint.Cap.ROUND);//圆形
canvas.drawLine(100, 500, 900, 500, paint);
paint.setStrokeCap(Paint.Cap.SQUARE);//方形
canvas.drawLine(100, 600, 900, 600, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStrokeJoin(Paint.Join.MITER);//锐角
path.moveTo(100, 1000);
path.lineTo(300, 1100);
path.lineTo(100, 1200);
canvas.drawPath(path, paint);
paint.setStrokeJoin(Paint.Join.ROUND);//圆弧
path.moveTo(100, 1300);
path.lineTo(300, 1400);
path.lineTo(100, 1500);
canvas.drawPath(path, paint);
paint.setStrokeJoin(Paint.Join.BEVEL);//直线
path.moveTo(100, 700);
path.lineTo(300, 800);
path.lineTo(100, 900);
canvas.drawPath(path, paint);
}
字体以及FontMetrics
在自定义View时,如果需要绘制字体,Android提供了如下方法:
drawText(String text, float x, float y, Paint paint)
这里参数text是一个String类型,就是需要绘制的文字,float类型的x和y需要着重介绍一下。
x跟Paint设置的setTextAlign()有关系,一般默认是LEFT,这时候x就是文字绘制的左侧起点。
y理解跟View中坐标有些不同,这里的y其实是一个基线,在TextView中设置的字体,垂直方向上面默认都是基线对齐。为了更好的理解基线,可以参看下图:
位于基线上面的值为负值,基线下面的值是负值。
Android提供了FontMetrics类定义了字体规格对象,该对象封装了有关在特定屏幕上呈现特定字体的信息。
ascent是baseline之上至字符最高处的距离。
descent是baseline之下至字符最低处的距离。
leading文档说的很含糊,其实是上一行字符的descent到下一行的ascent之间的距离。
top指的是指的是最高字符到baseline的值,即ascent的最大值。
bottom指的是最下字符到baseline的值,即descent的最大值。
在一些自定义控件中,如果需要将绘制的文本垂直居中,这时候我们就要重新计算baseLineY的值了,因为View本身坐标系是以左上角为原点,而绘制文字时是以基线BaseLine为参考线,需要将坐标系转换一下,根据下图可以很方面的得出转换公式。
float baselineY = centerY + (fontMetrics.bottom-fontMetrics.top)/2 - fontMetrics.bottom
如果指定左上角的顶点坐标绘制文本。
float baselineY = Y - fontMetrics.top。
将文本绘制完成后,如果计算文字所占的空间宽度呢。Android也提供了相应的方法。
public class PaintView extends View {
private static final String TAG = "PaintView";
private Paint paint;
private Path path;
private String str = "世界HelloWorld";
private Paint.FontMetrics fontMetrics;
private float baseY = 200;
public PaintView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
paint.setTextSize(120);
fontMetrics = paint.getFontMetrics();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(str, 100, baseY, paint);
paint.setColor(Color.RED);
canvas.drawLine(100, baseY, 950, baseY, paint);
float topY = baseY + fontMetrics.top;
paint.setColor(Color.GREEN);
canvas.drawLine(100, topY, 950, topY, paint);
float bottomY = baseY + fontMetrics.bottom;
paint.setColor(Color.GREEN);
canvas.drawLine(100, bottomY, 950, bottomY, paint);
float ascentY = baseY + fontMetrics.ascent;
paint.setColor(Color.YELLOW);
canvas.drawLine(100, ascentY, 950, ascentY, paint);
float descentY = baseY + fontMetrics.descent;
paint.setColor(Color.BLUE);
canvas.drawLine(100, descentY, 950, descentY, paint);
float[] measuredWidth = new float[1];
//计算指定长度的字符串(字符长度、字符个数、显示的时候真实的长度)
int breakText = paint.breakText(str, true, 1000, measuredWidth);
Log.i(TAG, "breakText="+breakText+", str.length()="+str.length()+", measuredWidth:"+measuredWidth[0]);
Rect bound=new Rect();
//获取文本的宽度,但是是一个比较粗略的结果
paint.getTextBounds(str,0,str.length(),bound);
Log.i(TAG, "getTextBounds="+bound.width());
//测量字符宽度
float measureText = paint.measureText(str);
Log.i(TAG, "measureText="+measureText);
float[] measuredWidths = new float[12];
//测量得到每一个字符的宽度;textWidths字符数
int textWidths = paint.getTextWidths(str, measuredWidths);
Log.i(TAG, "textWidths:"+textWidths+" "+ Arrays.toString(measuredWidths));
}
}
输出结果如下:
PaintView: breakText=12, str.length()=12, measuredWidth:814.0
PaintView: getTextBounds=800
PaintView: measureText=814.0
PaintView: textWidths:12 [114.0, 114.0, 86.0, 64.0, 29.0, 29.0, 68.0, 104.0, 68.0, 41.0, 29.0, 68.0]
android 画笔设置参数,Android画笔Paint和FontMetrics相关推荐
- android 拍摄视频设置参数,手机如何设置参数,才能拍出高清视频?
原标题:手机如何设置参数,才能拍出高清视频? 有的人用着最新款的手机,但是拍着最模糊的视频和照片. 所以,当你拿起手机的时候,要先了解它有什么功能,虽然现在智能手机都是自动设置的,但是也要根据自己的需 ...
- android 动态设置padding,Android动态设置控件大小以及设定margin以及padding值
http://www.aichengxu.com/Java/73893.htm Android动态设置控件大小以及设定margin以及padding值,有需要的朋友可以参考下. 一.概述 在andro ...
- android自定义设置界面,Android开发之精仿QQ设置界面(自定义PreferenceActivity)
Android开发之精仿QQ设置界面(自定义PreferenceActivity) 时间:2011-12-05 10:25:06 来源:Android开发者门户 作者: 今天,再给大家分享一下QQ设置 ...
- android imageview设置边框,android ImageView 添加边框
有两种方法可以给ImageView添加边框,一种是通过xml文件配置shape.另一种是重写ImageView的ondraw方法,这里用第二中方法: package org.example.image ...
- android 序列化传参数,android 传值 序列化
Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口. 0. ...
- android gridview设置高度,android设置GridView高度自适应,实现全屏铺满效果
使GridView每个item的高度自适应拉伸,达到整个GridView刚好铺满全屏的效果. public static void setGridViewMatchParent(GridView gr ...
- android remoteviews 设置背景,Android通过RemoteViews实现跨进程更新UI示例
一.概述 前面一篇文章Android通过AIDL实现跨进程更新UI我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新UI是可行的,但有以下弊端: View中的方法数比较多,在IPC中需要增加 ...
- android如何设置图标,Android APP如何设置显示图标
一款APP的图标是它的脸面,颜值的重要性,不言而喻了.接下来,如何设置APP的图标? 步骤1.编辑 AndroidManifest.xml: package="test.applicatio ...
- android+动态设置权重,Android自适应布局(关于权重weight的使用技巧!)
weight和weightSum Layout Weight LinearLayout also supports assigning a weight to individual children ...
最新文章
- struts2之单个文件上传
- SwiftUI之深入解析高级动画的时间轴TimelineView
- 搜索引擎学习(四)中文分词器
- 使用Modernizr探测HTML5/CSS3新特性
- rpm(centos)软件包管理工具
- mybatis中条件表达式if的test为字符串时值比较
- 跟我一起学Redis之看完这篇比常人多会三种类型实战(又搞了几个小时)
- 2021-11-05深度学习
- CVPR2020|无需3D运动数据训练,最新SOTA人体姿势估计方法
- Python3用requests,multiprocessing多线程爬取今日头条图片
- 使用Tika进行文本抽取
- vc red.msi matlab,vc_red.msi
- 【OpenCVOpenGLMarkerless AR】原理部分+代码
- JAVA 使用DateUtils对日期进行格式转换
- C盘空间不足怎么办?教你将其他盘存储空间分给C盘
- 大数据四大阵营之OLTP阵营(上)
- 戴尔联想惠普IT服务全方位比拼
- 【数据结构算法】-- C语言
- pytorch官方文档(中文版)
- LaTex 最狠的网站 嘎嘎狠