为了账号安全,请及时绑定邮箱和手机立即绑定

Android View多行文本居中

标签:
Android

涉及知识

绘制过程

类别

API

描述

布局

onMeasure

测量View与Child View的大小


onLayout

确定Child View的位置


onSizeChanged

确定View的大小

绘制

onDraw

实际绘制View的内容

事件处理

onTouchEvent

处理屏幕触摸事件

重绘

invalidate

调用onDraw方法,重绘View中变化的部分

(如果对绘制过程与构造函数还不了解的,请查看我之前文章http://www.apkbus.com/blog-705730-61796.html)

Canvas涉及方法

类别

API

描述

绘制图形

drawPoint, drawPoints, drawLine, drawLines, drawRect,   drawRoundRect, drawOval, drawCircle, drawArc

依次为绘制点、直线、矩形、圆角矩形、椭圆、圆、扇形

绘制文本

drawText, drawPosText, drawTextOnPath

依次为绘制文字、指定每个字符位置绘制文字、根据路径绘制文字

画布变换

translate, scale, rotate, skew

依次为平移、缩放、旋转、倾斜(错切)

画布裁剪

clipPath, clipRect, clipRegion

依次为按路径、按矩形、按区域对画布进行裁剪

画布状态

save,restore

保存当前画布状态,恢复之前保存的画布

Paint涉及方法

类别

API

描述

颜色

setColor,setARGB,setAlpha

依次为设置画笔颜色、透明度

类型

setStyle

填充(FILL),描边(STROKE),填充加描边(FILL_AND_STROKE)

抗锯齿

setAntiAlias

画笔是否抗锯齿

字体大小

setTextSize

设置字体大小

字体测量

getFontMetrics(),getFontMetricsInt()

返回字体的测量,返回值一次为float、int

文字宽度

measureText

返回文字的宽度

文字对齐方式

setTextAlign

左对齐(LEFT),居中对齐(CENTER),右对齐(RIGHT)

宽度

setStrokeWidth

设置画笔宽度

笔锋

setStrokeCap

默认(BUTT),半圆形(ROUND),方形(SQUARE)

PS: API较多,只列出了涉及的方法,想了解更多,请查看官方文档)

一、绘制文本

在Canvas中绘制文本,使用在上一篇绘制的坐标系

1、drawText

drawText的几种方法如下:

[代码]java代码:

?

1

2

3

4

public void drawText   (String text, float x, float y, Paint paint)

public void drawText   (String text, int start, int end, float x, float y, Paint paint)

public void drawText   (CharSequence text, int start, int end, float x, float y, Paint paint)

public void drawText   (char[] text, int index, int count, float x, float y, Paint paint)

 

x、y值表示绘制文本左下角的坐标

[代码]java代码:

?

1

2

3

4

5

6

Paint mPaint = new Paint();

mPaint.setAntiAlias(true);//抗锯齿

mPaint.setColor(Color.BLUE);//设置画笔颜色

mPaint.setTextSize(50);

String string = "Idtk";

canvas.drawText(string,0,0,mPaint);

 



或者只绘制其中的一部分字符
start表示从第几个字符开始,end表示到第几个字符之前结束

[代码]java代码:

?

1

canvas.drawText(string,1,4,0,0,mPaint);//截取第一到第四个字符

 



可以使用CharSequence绘制

[代码]java代码:

?

1

2

CharSequence charSequence = "charSequence";

canvas.drawText(charSequence,5,10,0,0,mPaint);

 



或者使用字符数组,index表示从第几个字符开始,count表示截取的数组长度

[代码]java代码:

?

1

2

char[] chars = "chars".toCharArray();

canvas.drawText(chars,2,3,0,0,mPaint);

 

 

2、drawPosText

给文本中的每个字符都设定一个坐标,但是已经不推荐使用。

3、drawTextOnPath

根据path绘制文本,不过path是一个比较重要且有趣的东西,在之后绘制折线图或者曲线图之前的涉及知识中会进行分析。drawTextOnPath的几种方法:

[代码]java代码:

?

1

2

public void drawTextOnPath   (String text, Path path, float hOffset, float vOffset, Paint paint)

public void drawTextOnPath   (char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)

 

这里简单写一个,path为一条从原点到(0,200)的直线,水平偏移量、垂直偏移量都设置为100,注意偏移量设置时不要过大,一面影响字符串的正常显示。

[代码]java代码:

?

1

2

3

Path path = new Path();

path.lineTo(0,200);

canvas.drawTextOnPath(string,path,100,100,mPaint);

 



另一种方法,和上面drawText中使用字符数组的方法,同理。

二、文本居中

1、单行文本居中

a、getFontMetrics(),getFontMetricsInt()

getFontMetrics(),getFontMetricsInt()用于返回字符串的测量,而两个方法的区别就是返回值得类型。返回值一共有五个属性:

·         Top : baseline到文本顶部的最大的距离

·         Ascent : baseline到文本顶部的推荐距离

·         Descent : baseline到文本底部的推荐距离

·         Bottom : baseline到文本底部的最大距离

·         Leading : 两行文本之间推荐的额外距离,一般为0

 

在Android的坐标系之中,向下为Y轴正方向,向上位Y轴负方向,所以baseline之上的Top与Ascent都是负数,而baselin之下的Descent、Bottom都是正数。如果要让字符串在垂直方向上居中,则需要在纵坐标上增加Asecent绝对值与descent的差。

leading值是一行文本的底部与下一行文本的顶部之间的距离,图中就是line1的橙色线条与line2的紫色线条之间测距离,一般情况下是0。根据stackoverflow中的说法,是一行的bottom与下一行的top已经为字符串提供了足够的空间,所以leading的值在一般情况下都为0。需要注意的是,在获取FontMetrics之前请完成Paint的设置,这样才能准确的获取测量值。

[代码]java代码:

?

1

2

3

4

5

mPaint.setTextSize(50);

String string = "Idtk";

Paint.FontMetrics fontMetrics=   mPaint.getFontMetrics();

float textHeight = (-fontMetrics.ascent-fontMetrics.descent)/2;

canvas.drawText(string,0,textHeight,mPaint);

 

 

b、setTextAlign

setTextAlign可以设置画笔绘制文本的对齐方式,选择center即可完成文本的水平居中。

[代码]java代码:

?

1

mPaint.setTextAlign(Paint.Align.CENTER);

 

 

c、measureText

measureText可以测量文本的宽度,即横向长度,这样也可以来完成居中设置,但在这之前,需要恢复文本对齐方式至默认设置(居左)。

[代码]java代码:

?

1

2

float textWidth = mPaint.measureText(string);

canvas.drawText(string,-textWidth/2,textHeight,mPaint);

 



我们可以看出结果与之前相同。

2、多行文本居中

这是整片博客来说最有趣的地方,我们如何让一个多行字符串居中呢?
假设有设定好的字符串数组,画笔,画布,坐标点

·         1、drawText每次只能绘制一行,所以我们有个for循环

·         2、更具上图,假设字符串数组大于1,每个字符串的高度应该为-top+bottom,总高度就为length*(-top+bottom);

·         3、偏移量就等于length*(-top+bottom)/2-bottom;

·         4、如果顺序向上(即Y负方向)排列的话,那么第i个字符串的高度就是-(length-i-1)*(-top+bottom);

·         5、每个字符串高度的减去偏移量,就应该是每个字符串的baseline的Y坐标

详细代码如下:

[代码]java代码:

?

1

2

3

4

5

6

7

8

9

private void textCenter(String[]   strings, Paint paint, Canvas canvas, Point point,Paint.Align align){

    mPaint.setTextAlign(align);

    Paint.FontMetrics   fontMetrics= mPaint.getFontMetrics();

    float top = fontMetrics.top;

    float bottom = fontMetrics.bottom;

    int length = strings.length;

    float total = (length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);

    float offset = total/2-bottom;

    for (int i=0; i<length; i++){="" float="" yaxis="-(length-i-1)*(-top+bottom)+offset;" canvas.drawtext(strings[i],point.x,point.y+yaxis,mpaint);="" }="" }<="" pre=""></length;>

 

偏移量取值的变化,是因为在字符串的首尾两个字符串,需要把top改成ascent,bottom改成descent。通过设置画笔来完成横向的居中,居左,居右。

使用代码:

[代码]java代码:

?

1

2

3

4

5

mPaint.setTextSize(50);

mPaint.setColor(Color.BLUE);

String[] strings = new String[]{"Idtk","是","一","个","小","学","生"

Point point = new Point(0,0);

textCenter(strings,mPaint,canvas,point,Paint.Align.CENTER);

 

 

3、多列文本居右

多列文本居右即模仿古文的书写方式

·         1、一个字符串数组,分割正多个字符数组

·         2、每个字符数组中,获取最宽的字符宽度,为字符数组的字符宽度

·         3、计算数组x坐标,再调用之前的文本居中代码

我们先重载一个textcenter方法:

[代码]java代码:

?

1

2

3

4

5

6

7

8

9

private void textCenter(char[]   chars, Paint paint, Canvas canvas, Point point,Paint.Align align){

    mPaint.setTextAlign(align);

    Paint.FontMetrics   fontMetrics= mPaint.getFontMetrics();

    float top = fontMetrics.top;

    float bottom = fontMetrics.bottom;

    int length = chars.length;

    float total = (length-1)*(-top+bottom)+(-fontMetrics.ascent+fontMetrics.descent);

    float offset = total/2-bottom;

    for (int i=0; i<length; i++){="" float="" yaxis="-(length-i-1)*(-top+bottom)+offset;" canvas.drawtext(chars[i]+"",point.x,point.y+yaxis,mpaint);="" }="" }<="" pre=""></length;>

 

接下来编写多列居左的代码:

[代码]java代码:

?

1

2

3

4

5

6

private void rowTextRigth(String[]   strings, Paint paint, Canvas canvas, Point point){

    mPaint.setTextAlign(Paint.Align.RIGHT);

    int length = strings.length;

    float len,newLen;

    float total = 0;

    for (int j=0; j<length; j++){="" char[]="" chars="strings[j].toCharArray();" len="mPaint.measureText(chars[0]+"");" for="" (int="" i="1;" i<chars.length;="" i++){="" newlen="mPaint.measureText(chars[i]+"");" }="" point.x="point.x" -="" (int)="" total;="" textcenter(chars,mpaint,canvas,point,paint.align.right);="" +="" total="total+len;" }<="" pre=""></length;>

 

使用方法示例:

[代码]java代码:

?

1

2

String[] strings2 = new String[]{"床前明月光,","疑是地上霜。","举头望明月,","低头思故乡。"};

rowTextRigth(strings2,mPaint,canvas,point);

 

 

4、文本自动换行居中

系统中有一个StaticLayout方法,可以在设置宽度,当前行文本超过此宽度后,进行自动换行,提供ALIGN_CENTER(居中)、ALIGN_NORMAL(标准)、ALIGN_OPPOSITE(与标准相反)三种对齐方式。
可以简单的封装成一个方法:

[代码]java代码:

?

1

2

3

4

5

6

7

8

private void textCenter(String   string, TextPaint textPaint, Canvas canvas, Point point, int width,

                        Layout.Alignment   align, float spacingmult,   float spacingadd,   boolean includepad){

    StaticLayout   staticLayout = new StaticLayout(string,textPaint,width,   align,spacingmult,spacingadd,includepad);

    canvas.save();

    canvas.translate(-staticLayout.getWidth()/2+point.x,-staticLayout.getHeight()/2+point.y);

    staticLayout.draw(canvas);

    canvas.restore();

}

 

使用方法,这里设置宽度为150:

[代码]java代码:

?

1

2

3

4

5

6

7

String mString = "Idtk是一个小学生";

TextPaint tp = new TextPaint();

tp.setColor(Color.BLUE);

tp.setStyle(Paint.Style.FILL);

tp.setTextSize(50);

Point point = new Point(0,0);

textCenter(mString,tp,canvas,point,150,Layout.Alignment.ALIGN_CENTER,1.5f,0,false);

 

三、小结

本文介绍了如何在canvas中绘制文字,以及单行、多行文字居中,多列文本居右。在下一篇文章将会迎来一个阶段性的目标,进行PieChart的绘制。如果在阅读过程中,有任何疑问与问题,欢迎与我联系。

 

 

原文链接:http://www.apkbus.com/blog-705730-61835.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消