自定义view(五):自定义view使文字居中对齐显示

来源:互联网 发布:linux启动u盘制作工具 编辑:程序博客网 时间:2024/05/21 17:15

接着上一篇文章 自定义view(四):自定义view实现动态按钮
今天在自定义view中加上一个文字显示。
本以为,这个挺简单的,但是没想到文字加上后,发现不居中。

设置了 mPaintTv.setTextAlign(Paint.Align.CENTER);发现只能文字左右居中,上下依然不是正中心。like this
这里写图片描述
中间的红线是中心线,但是文字却不是跟中心对齐的,而是文字底部跟中心线平齐。

这显然不符合按钮的显示啊,查阅了一下资料,发现,自定义view在drawText时候,这个文字的对齐还真的是有个小坑。

这里写图片描述

上图是从网上找到的,但是里面有一个坑,后面会讲。
**先解释下,drawText(String text,float x,float y,Paint paint)
里面的x参数,在paint未设置setTextAlign 时,默认是从横坐标x点处开始绘制第一个字符串的字符。
如果mPaintTv.setTextAlign(Paint.Align.CENTER);则是整个字符串的中心点的横坐标是x

里面的y参数永远都跟 字符串的Baseline对齐。**

这也就是为什么我们用矩形的中心点去绘制text的时候,文字却不在正中心,反而是有些向上偏移。
like this:这里写图片描述

所以绘制的时候我们要把文字偏移的那段距离算出来:
那么坑就出来了 :【前方高能】
通过Paint.FontMetrics fm = mPaintTv.getFontMetrics(); 可以获得字体属性类FontMetrics
FontMetrics 里面有两个很重要的属性就是ascentdescent

他们表示的不仅仅是如下图的距离,如果你debug过,会发现他们还带有正负号,
说实话,当时我感觉真是日了哈士奇了。后来我发现,这也是可以理解的。
就如图所示,以baseline为x轴,向下是正方向,向上为负方向。
所以ascent永远都是负值。

这里写图片描述

搞清楚了这一点,我们就可以大大方方的计算了。
如果想要文字居中显示,肯定是以中心线(虚线)为x轴了,但是现在是以baseline为x轴,只需要计算出中心线和baseline之间的距离即可(中心线与baseline之间的距离 = 中心线到底部的距离 - descent)。

首先:
中心线到底部的距离是 = 整个文字的高度 / 2 ;即(-ascent + descent)/2

中心线与baseline之间的距离 = (-ascent + descent)/ 2 - descent ;即 (-ascent-descent) / 2

然后,只需要在drawText时候将y参数向上提高 中心线与baseline之间的距离即可

canvas.drawText("bjjg",maxWidth/2,maxHeight/2 - (fm.descent - (-fm.ascent + fm.descent)/2),mPaintTv);

这里写图片描述

全部代码如下:

/** * Created by FanHaiChao on 2017/4/12. * 自定义的带动画的view */public class MyButtonView extends View {    private Paint mPaintBg;    private Paint mPaintTv;    private RectF rect;    private float radius;    private int index = 0;    private int maxIndex = 24;    private boolean isDraw = false;//是否绘制完成:true--绘制完成;false--未绘制完成    private boolean isTo0 = false;//true:变显示, false:变消失    public MyButtonView(Context context) {        this(context,null);    }    public MyButtonView(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    public MyButtonView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    private void initView() {        mPaintBg = new Paint();        mPaintBg.setAntiAlias(true);        mPaintBg.setStyle(Paint.Style.FILL);        mPaintBg.setColor(Color.RED);        mPaintTv = new Paint();        mPaintTv.setAntiAlias(true);        mPaintTv.setStyle(Paint.Style.FILL);        mPaintTv.setColor(Color.WHITE);        mPaintTv.setTextSize(36);        mPaintTv.setTextAlign(Paint.Align.CENTER);    }    //每一帧 onDraw一次  index变一次 ondraw一次    //注意onDraw 方法 会在view所在activity可见时调用,也就是说 view 重新可见时 也会调用onDraw    @Override    protected void onDraw(Canvas canvas) {        if (isDraw) {            float maxWidth = getWidth();            float maxHeight = getHeight();            if (index <= (maxIndex / 2)) {//前一半时间画圆,后一半时间画圆角矩形                canvas.drawCircle(maxWidth / 2, maxHeight / 2, radius, mPaintBg);                radius = ((maxHeight / 2) / (maxIndex / 2)) * index;            } else {                if (maxWidth > maxHeight) {                    radius = maxHeight / 2;                } else {                    radius = maxWidth / 2;                }                float wr = ((maxWidth / 2 - radius) / (maxIndex / 2)) * (index - maxIndex/2);                //参数:左边距,上边距,右边距,下边距                rect = new RectF(maxWidth / 2 - radius - wr, 0, maxWidth / 2 + radius + wr, 2 * radius);                canvas.drawRoundRect(rect, 90, 90, mPaintBg);                canvas.drawLine(0,maxHeight/2,maxWidth,maxHeight/2,mPaintTv);                Paint.FontMetrics fm = mPaintTv.getFontMetrics();                canvas.drawText("暴躁的码字猴",maxWidth/2,maxHeight/2 - (fm.descent - (-fm.ascent + fm.descent)/2),mPaintTv);            }            if (isTo0) {                index--;            } else {                index++;                index = index <= maxIndex ? index : maxIndex;            }            if (index <= maxIndex && index >= -1) {                invalidate();            } else {                System.out.println(index);            }        }    }    public void startShow(boolean draw) {        isDraw = draw;        if (index == maxIndex){            isTo0 = true;            radius= 0;        }else {            isTo0 = false;            radius= 0;        }        invalidate();    }}
1 0
原创粉丝点击