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

来源:互联网 发布:task host windows 10 编辑:程序博客网 时间:2024/05/29 08:20

我们在绘制文字的时候是通过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);        }    }}
这个代码简单,没啥可解释的,看效果:


原创粉丝点击