有关自定义控件的许多内容,一直都想抽时间梳理一下,当然了梳理的内容不会很深,都是一些比较常用的类或者方法,主要是为了后续用到时方便查阅与参考。

本文主要整理的是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相关推荐

  1. android 拍摄视频设置参数,手机如何设置参数,才能拍出高清视频?

    原标题:手机如何设置参数,才能拍出高清视频? 有的人用着最新款的手机,但是拍着最模糊的视频和照片. 所以,当你拿起手机的时候,要先了解它有什么功能,虽然现在智能手机都是自动设置的,但是也要根据自己的需 ...

  2. android 动态设置padding,Android动态设置控件大小以及设定margin以及padding值

    http://www.aichengxu.com/Java/73893.htm Android动态设置控件大小以及设定margin以及padding值,有需要的朋友可以参考下. 一.概述 在andro ...

  3. android自定义设置界面,Android开发之精仿QQ设置界面(自定义PreferenceActivity)

    Android开发之精仿QQ设置界面(自定义PreferenceActivity) 时间:2011-12-05 10:25:06 来源:Android开发者门户 作者: 今天,再给大家分享一下QQ设置 ...

  4. android imageview设置边框,android ImageView 添加边框

    有两种方法可以给ImageView添加边框,一种是通过xml文件配置shape.另一种是重写ImageView的ondraw方法,这里用第二中方法: package org.example.image ...

  5. android 序列化传参数,android 传值 序列化

    Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口. 0. ...

  6. android gridview设置高度,android设置GridView高度自适应,实现全屏铺满效果

    使GridView每个item的高度自适应拉伸,达到整个GridView刚好铺满全屏的效果. public static void setGridViewMatchParent(GridView gr ...

  7. android remoteviews 设置背景,Android通过RemoteViews实现跨进程更新UI示例

    一.概述 前面一篇文章Android通过AIDL实现跨进程更新UI我们学习了aidl跨进程更新ui,这种传统方式实现跨进程更新UI是可行的,但有以下弊端: View中的方法数比较多,在IPC中需要增加 ...

  8. android如何设置图标,Android APP如何设置显示图标

    一款APP的图标是它的脸面,颜值的重要性,不言而喻了.接下来,如何设置APP的图标? 步骤1.编辑 AndroidManifest.xml: package="test.applicatio ...

  9. android+动态设置权重,Android自适应布局(关于权重weight的使用技巧!)

    weight和weightSum Layout Weight LinearLayout also supports assigning a weight to individual children ...

最新文章

  1. struts2之单个文件上传
  2. SwiftUI之深入解析高级动画的时间轴TimelineView
  3. 搜索引擎学习(四)中文分词器
  4. 使用Modernizr探测HTML5/CSS3新特性
  5. rpm(centos)软件包管理工具
  6. mybatis中条件表达式if的test为字符串时值比较
  7. 跟我一起学Redis之看完这篇比常人多会三种类型实战(又搞了几个小时)
  8. 2021-11-05深度学习
  9. CVPR2020|无需3D运动数据训练,最新SOTA人体姿势估计方法
  10. Python3用requests,multiprocessing多线程爬取今日头条图片
  11. 使用Tika进行文本抽取
  12. vc red.msi matlab,vc_red.msi
  13. 【OpenCVOpenGLMarkerless AR】原理部分+代码
  14. JAVA 使用DateUtils对日期进行格式转换
  15. C盘空间不足怎么办?教你将其他盘存储空间分给C盘
  16. 大数据四大阵营之OLTP阵营(上)
  17. 戴尔联想惠普IT服务全方位比拼
  18. 【数据结构算法】-- C语言
  19. pytorch官方文档(中文版)
  20. LaTex 最狠的网站 嘎嘎狠

热门文章

  1. 内推|滴滴招聘:销售策略运营+产品与用户运营+商业经营分析,|李锦记招聘:数据分析师...
  2. 为什么感冒会引起眼睛视力的下降?
  3. 2021-01-20 腊八节快乐
  4. 萝卜家园GHOST WIN7 装机版 2013 03
  5. 程序员健康面临的5大问题
  6. AD怎么输入坐标_CAD没有保存怎么办 CAD是会自动保存设置技巧
  7. devenv命令行编译项目
  8. ZZ最近做了温水煮青蛙的试验 感觉真的上当了
  9. 竹间科技以认知转型提升客户洞察能力
  10. 抓球球的机器人应该怎么玩_英雄联盟lol机器人怎么玩 机器人玩法技巧