Paint之文字相关

来源:互联网 发布:知乎健身教练要求 编辑:程序博客网 时间:2024/05/16 08:42

上文将Paint相关的类划分成了文字相关、图形相关、图像相关、随意图形四个部分。那么,今天就来说说这个文字相关的部分。
文字部分的API是最不好的分类的。哥将Paint里面和字体有关的方法挑选出来后,将各个方法进行划分,发现TM竟然不好划分,这可苦逼了哥。不过皇天不负有心人,总算出来一种哥自认为最好的划分的方式。废话不多说,有图有真相,直接上图。
这里写图片描述

什么叫做一些只有获取的方法!!!! 什么叫做 这些牛逼方法能够使用setter设置,也能使用getter方法来获取 !!!!!!!!!
这些逗比问题不解释,就喜欢任性命名一些东西~~~咋滴不满意?来看后面的内容会让你满意的。。。。。
从上到下,先说说一些只有获取的方法。

getFontMetric
说这个方法,我们先看SDK是怎么解释的。
这里写图片描述
看!!看!!返回设置了typeface,textSize的字体推荐的不同行之间的间距,如果metrics传入的是空值,返回的则是FontMetrics对象的值。(看哥没过四级的翻译,你们过了四级的肯定知道FontMetrics是字体测量的意思啦!!所以不用蹩脚的英文翻译来解释类名了)
上面的话,透露了太多信息! (神马信息??我怎么没想到?)返回设置了typeface,textSize的字体推荐的不同行之间的间距,这里是说返回FontMetrics对象中的值与typeface,textSize有关。
嗦嘎,那FontMetrics中有什么值呢?我们来看看源码~~
Duang~~Duang源码时间到
这里写图片描述
打开一看,吓了一跳。全是属性构成的类,这就是说,只要弄清楚这些属性是什么意思,就知道FontMetrics类具体是干什么的!!没错就是这样,我们通过一幅图来说明上面的属性。
这里写图片描述
(注:上图节选自,博客http://blog.csdn.net/aigestudio/article/details/41447349)
Ascent,上坡度。Desent,下坡度。Baseline,基准线。Leding,行间距。嗯,这就是上图里面涉及到FontMetrics类的中的相关属性。
来,我们先说说Baseline,从上面FontMetrics类中我们可以看到根本就没有baseline这个属性,但是,,所有的属性都是和这个baseline相关的定义。那为什么baseline有这么强大,能够统领FontMetrics类相关的属性,带领三军,杀入Android文字编写核心?这个个中缘由的来龙去脉要看Android文字绘制机制。
说Android文字绘制机制之前,我们先思考一个问题!! 文字是怎么在屏幕上显示的!!
和前文Paint概述中描述Bitmap格式的图像一样,文字也是由一个个像素点组成。但是这些像素点如何形成文字呢?google给出的答案就是baseline。baseline作为一把见到,将你要在屏幕上显示的文字,咔擦咔擦的,剪成了上下两半。上面的也就是baseline向上至字符最高处的Ascent(上坡度)。下面的就是baseline向下至字符最低处的Descnt(下坡度)。这里只是解决了单行的文字书写,那么多行呢?leading啦!!用来控制多行文字之间的间距。来扯了写东西,还是上段代码给诸位。

  @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawText(mTestText, mScreenWidth / 2, mScreenHeight / 2,                mTextPaint);        FontMetrics fontMetrics = mTextPaint.getFontMetrics();        //不推荐这样写法,这里只是为了说明FontMetrics的属性        Log.i(this.getClass().getSimpleName(), "Ascent  " + fontMetrics.ascent);        Log.i(this.getClass().getSimpleName(), "Desent  " + fontMetrics.descent);        Log.i(this.getClass().getSimpleName(), "leading " + fontMetrics.leading);        Log.i(this.getClass().getSimpleName(), "top     " + fontMetrics.top);        Log.i(this.getClass().getSimpleName(), "bottom  " + fontMetrics.bottom);    }

我们看到Logcat中输出的结果如下:
这里写图片描述
看到上面参数,你肯定在想,为什么bottom的数值大于top 上坡度值却比下坡度值要小!!这是Android文字绘制是将baseline作为起始,然后FontMetrics相关属性都是相对于这个baseline来产生偏移。和Android屏幕的xy坐标系一样,从Ascent到Descent之间的数值都是从小到大的,所以这里出现Ascent比Descent要小的原因。
说到这里,或许你已经在疑惑,你说的baseline是不是正确呢?我咋知道你不是胡扯的呢?能想到这点说明你很了不起。敢于质疑,才能更好的学习。来我们继续用代码来证明baseline的存在。

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    float textX = mTextPaint.measureText(mTestText);    // 这里我们原意是想将字符串绘制在屏幕的中央    canvas.drawText(mTestText, (mScreenWidth - textX) / 2,    mScreenHeight / 2, mTextPaint);    // 绘制屏幕正中央、与文字等宽的线 这条线就是baseline    canvas.drawLine((mScreenWidth - textX) / 2, mScreenHeight / 2,        (mScreenWidth + textX) / 2, mScreenHeight / 2, mLinePaint);}

这里写图片描述
我们看到上面的代码运行的效果完全不是我们所想要的。那么,现在假定baseline是存在的,将前面定义的baseline下移,然后将需要绘制的字符串居中显示。问题是下移多少呢?
下移距离计算其实可以使用如下的计算方法:

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    float textX = mTextPaint.measureText(mTestText);    FontMetrics fontMetrics = mTextPaint.getFontMetrics();    float lessValue = (Math.abs(fontMetrics.ascent) - Math.abs(fontMetrics.descent));    // 这里我们原意是想将字符串绘制在屏幕的中央    canvas.drawText(mTestText, (mScreenWidth - textX) / 2, mScreenHeight / 2 + lessValue / 2, mTextPaint);    // 绘制与文字等宽的线    canvas.drawLine((mScreenWidth - textX) / 2, mScreenHeight / 2,    (mScreenWidth + textX) / 2, mScreenHeight / 2, mLinePaint);}
lessValue代表着上坡度值到baseline的距离与下坡度值到baseline的距离,两者之间的差值就是距离差,将距离差等分,然后将baseline上(下)移动个距离差等分的距离,这样我们就将文字在屏幕正中间绘制。其实在这里我们就可以看出Android文字绘制中存在着一条隐藏的准则线。这也就是为什么ascent的值永远是不大于0的值的原因。FontMetrics还有两个属性:top、bottom。说到这两个属性,SDK上面给出的说明是:

给定字体类型及大小之后距离baseline最大的图形距离值。bottom与之相反,但是这两个属性没怎么具体用过,具体作用有待考察。
我们用一幅图来总结FontMetrics的属性:
这里写图片描述
但是值得注意的一点是FontMetrics的属性值仅仅只与字体以及字体大小有关。若想知道怎么设置字体以及字体大小,请见下文setTypeface()、setTextSize()等方法。

getFontMetircsInt
该方法就是将前面的FontMetrics的属性类型由float转换成了int。不予详细解释。

breakText
对于这个方法我们看SDK的解释。
这里写图片描述
该方法用于测量指定宽度里面能够存放多少个字符,SDK说明的比较详细,不予细说。

measureText
这里写图片描述
返回测量字符串的宽度,该方法可以用在将某行文字用于居中。这个案列将在后文中模仿控件中说明。

getFontSpacing
获得行间距。即两行文字之间的间距。后面在怎么显示多行文字,以及模拟多行文字的显示中使用的案例中将提到。

getBounds
获取对接近文字的矩形边框。该方法可以使用在对于选定文字设置背景色。

getTextWidths
返回字符串中某些字符的所占有的宽度

setCompatibilityScaling
设置可兼容的缩放。

上面说完了一些只有获取的方法后,是不是有些不满意这些方法实质就只介绍了FontMetrics?后面的方法讲起来没有什么意思,一眼能懂。后文中,我们将在模仿案例中来使用上述方法。我们发现上文Paint概述中文字部分涉及的类中还有Paint.Align、Typeface以及子类TextPaint等方法还没说。所以下面将在API方法中为你一一介绍这些类。

setFakeBoldText
设置伪粗体。用的不是很多

setTypeface
设置字体风格
Typeface类是一个很简单的类。对应方法如下:
这里写图片描述
这对应的字体文件可以存放在assent文件夹下面。

setTextLocale
SDK中对该方法的描述如下:
这里写图片描述
上述意思:设置文本语言环境。文本语言环境将影响一些语种的语言怎么绘制。例如,如果这个本地化设置是Locale.CHINESE或者是Locale.CHINA,那么文字渲染器将使用中文字体更好的绘制文本。与之相似的,如果本地化设置是Locale.JAPANES或者Locale.JAPAN,那么这个文字渲染器将使用日文字体更好的绘制文本。这样的区别是十分重要的,虽然中文字体和日文字体都使用相似的Unicode字符集,但是他们的呈现仍然有细微的区别。默认方式,文本语言环境是使用系统本地化来初始化的,该效果类似于调用了Locale.getDefault(),这里假设用户首选语言是文本渲染器的最佳选项。如果能够确认文本是什么文字,那么使用该方法能给文本提供更好的渲染效果。在文本独立绘制的语言区域里,文本渲染器将尝试选择语言脚本。在某种模棱两可的情形下,指定文本语言环节,将帮助渲染器更好的工作。
Locale是本地化,其实这个还有一个功能就是实现App的国际化。这个功能将在后文中说明。

setAlign
这里写图片描述
设置文本的对齐方式,对Paint.Align仅仅只有三个枚举值,CENTER、LEFT、RIGHT三者意思是文本居中,文本左对齐,文本右对齐。

setTextScaleX
这里写图片描述
设置文本在X轴上面的拉伸

setTextSize
设置文本绘制的大小,该设置会影响FontMetrics中的属性值

setTextSkewX
设置文本倾斜,官方推荐值是-0.25。

setStrikeThruText
设置带有删除线的效果

setUnderLineText
设置带有下划线的效果

0 0