您的位置:首页 > 移动开发 > Android开发

android drawText()方法中x,y坐标值真正的 意义

2017-08-27 17:38 435 查看
我们在绘制文字的时候是通过canvas的drawText(String text, float x, float y,Paint paint)方法第一个和第四个参数都知道,但是x,y知道传的是什么坐标么,其实传的是基线值,因为在绘制文字的时候有几个值要了解下:



是不是有点像学音乐的线谱,现在简单说明下

top,bottom是文字绘制的时候绝对不能超过的,也就是高不能超过top,底部不能超过bottom.

asent,descent是系统建议不要超过的,但是有时候绘制文字会超过,比如你绘制一个g字母下面可能就会 超过descent

而x,y就是指baseline(基线)为准的值,我们在这画一个坐标:



通过上面的坐标我们知道top和ascent是负值 而bottom和descent是正值

从上面的坐标我们可以得到如下几个等式:

top = top线的y坐标 - baseline线的y坐标
bottom = bottom线的y坐标 - baseline线的y坐标
ascent = ascent线的y坐标 - baseline线的y坐标
desent = desent线的y坐标 - baseline线的y坐标

在android中top bottom ascent descent其实已经封装成类了在Paint内部类有一个:

public static class FontMetrics {
/**
* The maximum distance above the baseline for the tallest glyph in
* the font at a given text size.
*/
public float   top;
/**
* The recommended distance above the baseline for singled spaced text.
*/
public float   ascent;
/**
* The recommended distance below the baseline for singled spaced text.
*/
public float   descent;
/**
* The maximum distance below the baseline for the lowest glyph in
* the font at a given text size.
*/
public float   bottom;
/**
* The recommended additional space to add between lines of text.
*/
public float   leading;
}

leading指的是行间距

通过FontMetrics转化下:

      bottom = baseline + FontMetrics.bottom
top = baseline + FontMetrics.top

而我们是要求y坐标的值,如下图:



文字中心其实就是view的高度一半,这是个已知值,我们只要求出C的坐标然后加上啊+view高度的一半就是y的值,

图中A和B的值是相等的

A=B = (bottom - top)/2 这里A和B指的是长度

而    bottom = baseline + FontMetrics.bottom
top = baseline +FontMetrics.top

所以A=B = FontMetrics.bottom/2-FontMetrics.top/2,而C=B-bottom的值也就是 FontMetrics.bottom/2-FontMetrics.top/2-(baseline
+ FontMetrics.bottom)

而C又等于baseline-center  所以是baseline-center = B-(bottom-baseline)也就是baseline-center = B-(baseline+FontMetrics.bottom-baseline)结果是:

baseline-center = FontMetrics.bottom/2-FontMetrics.top/2-FontMetrics.bottom

而center=view.getHeight/2所以baseline=FontMetrics.bottom/2-FontMetrics.top/2-FontMetrics.bottom+view.getHeight/2;

也就是y的值是FontMetrics.bottom/2-FontMetrics.top/2-FontMetrics.bottom+view.getHeight/2;最终优化下算法是

y=-(FontMetrics.bottom+FontMetrics.top)/2+view.getHeight/2

这个如果在一个圆中绘制文字,如果计算不对的话也就是不在中心点很容易看的出来,现在就写一个简单的demo,自定义一个CircleProgressView

代码如下:

package com.example.circleprogressview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by zhouguizhi on 2017/8/27.
*/
public class CircleProgressView extends View {
private int max = 100;
private Paint paint;
private float progress = 0;
private int roundColor =Color.parseColor("#008080");
private int textColor = Color.parseColor("#696969");
private int roundProgressColor = Color.parseColor("#DEB887");
private float textSize = 40;
private float roundWidth = 24;
private int percent = 0;

public CircleProgressView(Context context) {
this(context,null);
}
public CircleProgressView(Context context,  AttributeSet attrs) {
this(context, attrs,0);
}
public CircleProgressView(Context context,  AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
}
private void initPaint() {
paint = new Paint();
paint.setColor(roundColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(roundWidth);
paint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircle(canvas);
drawText(canvas);
drawOval(canvas);
postDelayed(new Runnable() {
@Override
public void run() {
progress += 1;
if(progress>100){
return;
}
postInvalidate();
}
},100);
}
private void drawOval(Canvas canvas) {
if(null!=canvas){
RectF oval = new RectF(roundWidth/2, roundWidth/2, getWidth()-roundWidth/2, getWidth()-roundWidth/2);
paint.setColor(roundProgressColor);
paint.setStrokeWidth(roundWidth);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawArc(oval, 0 , 360 * progress / max, false, paint);
}
}
private void drawText(Canvas canvas) {
if(null!=canvas){
paint.setColor(textColor);
paint.setStrokeWidth(0);
paint.setTextSize(textSize);
percent = (int)(progress / (float)max * 100);
String strPercent = percent + "%";
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
if(percent != 0){
canvas.drawText(strPercent, getWidth() / 2 - paint.measureText(strPercent) / 2 ,
getHeight() / 2-(fm.bottom+fm.top)/2, paint);
}
}
}
private void drawCircle(Canvas canvas) {
if(null!=canvas){
float radius = getWidth() / 2 - roundWidth/2;
paint.setStrokeWidth(24);
canvas.drawCircle(getWidth() / 2,getWidth() / 2,radius,paint);
paint.setColor(roundColor);
canvas.drawCircle(getWidth() / 2,getWidth() / 2,radius,paint);
}
}
}

这个代码简单,没啥可解释的,看效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: