绘制系列(五)-DrawText()详解

绘制系列(五)-DrawText()详解

文字基础知识

1、setTextAlign()

设置文字对齐方式(起始点相对于文字)

canvas.drawText(“文字”,起始点,paint)

比如: paint.setTextAlign(Paint.Align.RIGHT)//表示起始点在文字的右侧开始绘制;

###2、设置字体样式 ###

  1. 设置粗体 setBoldText(boolean fakeBoldText)
  2. 设置下划线 setUnderLineText(boolean underLineText)
  3. 设置是否显示中间删除线 setStrikeThruText()
  4. 设置字体倾斜度 setTextSkewX(float skewX),取负值向右倾斜,取正值向左倾斜
  5. 水平拉伸 setTextScaleX(floate scaleX)取值为1,表示不拉伸
  6. 设置字体seTypeface(Typeface typeface);Typeface是字体样式的类,可以指定系统中的字体,也可以在自定义样式文件中获取

字体样式

  • Android中自带的字体样式,Typeface类中保存着三种自带字体样式,Typeface。SAN_SERIF、Typeface.MONOSPACE、Typeface.SERIF,这三种的字体对中文支持不很有友好,当遇到不支持的文字时,会使用系统默认的样式来写;

-Typeface create(String familyName,int style)
通过指定字体名来加载系统中自带的字体样式,如果字体样式不存在,则会用紫铜样式代替并返回;

一般情况下,我们会选择加载自定义的字体文件来绘制文字,而不是指定系统自带的字体样式;
要自定义字体样式:

  1. 从外部字体文件中加载所需字形

     Typeface createFromAsset(AssetManager mgr,String apth)
    
     createFromFile(String path)
    
     createFromFile(File path)
    

绘制文字

  1. public void drawText(String text, float x, float y,Paint paint)
  2. public void drawText(String text, int start, int end, float x, float y,Paint paint)
  3. public void drawText(CharSequence text, int start, int end, float x, float y,Paint paint)
  4. public void drawText(char[] text, int index, int count, float x, float y,Paint paint)
  5. public void drawTextOnPath(char[] text, int index, int count,Path path,float hOffset, float vOffset,Paint paint)
  6. public void drawTextOnPath(String text,Path path, float hOffset,float vOffset,Paint paint)

大同小异,第二种、第四种只是截取某一段文字绘制,重点说一下第五种:沿路径绘制hOffset指路径水平位置的偏移量;vOffset:值起始点垂直偏移量

	 @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Path path = new Path();
    path.addCircle(220,300,100, Path.Direction.CCW);
    canvas.drawLine(220,300,320,300,paint);
    canvas.drawPath(path,paint);
    canvas.drawLine(600,300,700,300,paint);
    Path path1 = new Path();
    path1.addCircle(600,300,100, Path.Direction.CCW);
    canvas.drawPath(path1,paint);
    paint.setColor(Color.GREEN);
    canvas.drawTextOnPath("Linleslie",path,0,0,paint);
    canvas.drawTextOnPath("Linleslie",path1,80,-30,paint);


}

绘制系列(五)-DrawText()详解_第1张图片

可以看见路径时有方向的,这儿是逆时针方向,逆时针方向看做X轴方向,那么按照Android里面的坐标轴,由圆心指向外部的方向即为Y坐标正方向,所以这里vOffset位负值,其实就是圆内偏移;

位文字基线

绘制系列(五)-DrawText()详解_第2张图片
写英文是,对字母是有格式的,即四格线。DrawText()绘制文字也是有要求的,即基线。这里的第三条线就是基线。
绘制系列(五)-DrawText()详解_第3张图片

注意:关于上面函数中x、y参数说明,这里的(x,y)并不是绘制文字所在矩形的左上角坐标,而是文字基线起始坐标;y:即为基线位置;x:表示文字开始绘制的位置

文字对齐方式

通过setAlign()设置

居中对齐:x坐标相对于文字矩形的位置,即X坐标在文字矩形的正中间

左对齐:x坐标相对于文字矩形的位置,即X坐标和文字矩形的左边重合
右对齐:

DrawText()文字的四格线

绘制系列(五)-DrawText()详解_第4张图片

除了基线以外,如上图所示,另外还有四条线,分别是ascent,descent,top,bottom,他们的意义分别是:

ascent: 系统建议的,绘制单个字符时,字符应当的最高高度所在线
descent:系统建议的,绘制单个字符时,字符应当的最低高度所在线
top: 可绘制的最高高度所在线
bottom: 可绘制的最低高度所在线

ascent是绘制文字推荐绘制的最高高度,文字尽量在这个高度下绘制,descent是绘制文字推荐的最低高度,文字最好在这个位置上绘制。top线则指该文字可以绘制的最高高度线,bottom则是表示该文字可以绘制的最低高度线

FontMetrics类讲解##

上面我们说了,文字除了基线,还有四条线。如何获得其位置呢?即通过FontMetrics实现,该类内部有四个成员变量

FontMetrics::ascent;  
FontMetrics::descent;  
FontMetrics::top;  
FontMetrics::bottom;

其值计算方法为:
ascent = ascent线的y坐标 - baseline线的y坐标;//该值为负
descent = descent线的y坐标 - baseline线的y坐标;//该值为正
top = top线的y坐标 - baseline线的y坐标;
bottom = bottom线的y坐标 - baseline线的y坐标;

获取FontMetric对象

FontMetrics fontMetrics=paint.getFontMetrics();

Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();

FontMetrics和FontMetricsInt这两个雷其实是一样的,只是前者得到四个成员变是float类型和后者是int类型

文字宽度、高度、最小矩形

绘制系列(五)-DrawText()详解_第5张图片

文字宽度:绿色矩形宽度
文字高度:绿色矩形高度(即我上面我们说的及格线top-bottom距离)
最小矩形(即仅仅包裹文字的最小矩形):红色矩形

获取文字宽度

int width=paint.MeasureText(String text);

即可获取文字宽度

获取文字高度

我们说,文字高度其实就是四格线中top到bottom的距离,

Paint.FontMetricsInt fm = paint.getFontMetricsInt();

而top=baseLineY+fm.top;
bottom=baseLineY+fm.bottom;
所以height=bottom-top;

获取文字最小矩形

要获取最小矩形,也是通过系统函数来获取的

获取指定字符串所对应的最小矩形,以(0,0)点所在位置为基线 
 * @param text  要测量最小矩形的字符串 
 * @param start 要测量起始字符在字符串中的索引 
 * @param end   所要测量的字符的长度 
 * @param bounds 接收测量结果 
getTextBounds(String text,int start,int end,Rect minRect);

即可得到文字最小矩形minRect的相关参数.
这里特别要注意的是:

  1. 这里是以(0,0)为基线的,如果需要的真实的最小矩形边界参数需要在其minRect的minRect.top和minRect.bottom加上BaseLineY的值。

下面以demo测试一下:

 int baseLineY = 200;
int baseLineX = 0 ;
String text = "harvic\'s blog";
Paint paint = new Paint();
//设置paint
paint.setTextSize(120); //以px为单位
canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
Log.e("MyView",minRect.toShortString());

绘制系列(五)-DrawText()详解_第6张图片

从log打印的日志可以看出最小矩形的左上角,Y坐标为负,为什么呢?上面我们说了getTextBounds()默认是以(0,0)为基线的,所以要拿到最小矩形的实际top和bottom必须在此基础上在加上基线baseLinearLayoutY;即:
int top=minRect.top+baseLinY ;
int bottom=minRect.bottom+baseLineY;

最后在详细的,实现一下整个过程:

int baseLineY = 200;
int baseLineX = 70 ;
String text = "harvic\'s blog";
Paint paint = new Paint();

//设置paint
paint.setTextSize(120); //以px为单位
/*canvas.drawText("harvic\'s blog", baseLineX, baseLineY, paint);
Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
Log.e("MyView",minRect.toShortString());*/

//1.画Text所占区域
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float top=baseLineY+fontMetrics.top;
float bottom= baseLineY + fontMetrics.bottom;
float width= paint.measureText(text);
canvas.drawRect(baseLineX,top,baseLineX+width,bottom,paint);
//2.画最小矩形
Rect minRect= new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
Log.d("MyView", "minRect:" + minRect);
Log.d("MyView", "minRect.height():" + minRect.height());
Log.d("MyView", "fontMetrics.ascent-fontMetrics.ascent:" + (fontMetrics.ascent - fontMetrics.ascent));
paint.setColor(Color.RED);
canvas.drawRect(baseLineX+minRect.left,minRect.top+baseLineY,baseLineX+minRect.right,minRect.bottom+baseLineY,paint);
//3.画文字
paint.setColor(Color.YELLOW);
canvas.drawText(text,baseLineX,baseLineY,paint);

注意:画文字所占区域时,是和文字对齐方式有关的(paint.setAlign())。系统默认左对齐(baseLineX在文字区域的左边),所以其区域坐标是这样。如果是右对齐,该区域的left=baseLinX-width,right=baseLineX;

效果图:

绘制系列(五)-DrawText()详解_第7张图片

你可能感兴趣的:(绘制系列(五)-DrawText()详解)