赞
踩
我们在使用TextView去显示一段文本时,如果遇到一些特殊情况,比如我们希望文本显示的时候并不局限于显示单一的颜色,而是希望显示渐变色,或者是在做一个类似酷狗、网易云音乐的歌词显示动画效果的时候,这个时候如果使用系统为我们提供的TextView并不能满足我们的要求,因此就需要我们自己去绘制文字。
public class CustomTextView extends AppCompatTextView { private Paint mPaint; public CustomTextView(Context context) { this(context, null); } public CustomTextView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } @Override protected void onDraw(Canvas canvas) { //需要自己绘制文字,所以不能调用父类的实现 //super.onDraw(canvas); mPaint.setStyle(Paint.Style.FILL); mPaint.setTextSize(getTextSize()); mPaint.setColor(getCurrentTextColor()); canvas.drawText(getText().toString(), 0f, 0f, mPaint); } }
<com.aykj.textmeasuredemo.widget.CustomTextView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="abpa"
android:textSize="20sp"
android:textColor="#f00"/>
只分析代码的话,此时文字应该会被绘制在左上角的位置,那么运行起来看一下:
实际上并没有,实际上可以看到只有字母’p’的尾巴露出来了,那么,在绘制的时候,我们重新改变纵坐标的值试试看:
@Override
protected void onDraw(Canvas canvas) {
//需要自己绘制文字,所以不能调用父类的实现
//super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getCurrentTextColor());
canvas.drawText(getText().toString(), 0f, 30f, mPaint);
}
可以看到,文字的显示出来了,但是并没有完全显示,那么,纵坐标的值应该取多少合适?
那么,结合上图,对于上面的情况,我们只需要将纵坐标的值设置为-1*top即可,top的值可以通过Paint.FontMetrics对象获取
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getCurrentTextColor());
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
canvas.drawText(getText().toString(), 0f, -fontMetrics.top, mPaint);
}
接下来,把TextView的宽高都改为match_parent:
这个时候,我们希望文字在水平方向、垂直方向都居中,应该怎么来做呢?
文字水平居中比较简单,有两种方式:
指定Paint的TextAlign为center,并设置绘制的横坐标为控件宽度的一半
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getCurrentTextColor());
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
canvas.drawText(getText().toString(), getWidth()/2, -fontMetrics.top, mPaint);
}
不指定Paint的TextAlign,默认为left,设置绘制的横坐标为(控件宽度 - 文字宽度)的一半
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getCurrentTextColor());
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float textWidth = mPaint.measureText(TEXT, 0, TEXT.length());
canvas.drawText(getText().toString(), (getWidth() - textWidth)/2f, -fontMetrics.top, mPaint);
}
先试试把绘制的纵坐标设置为控件的高度/2
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
//绘制水平中线,测试文字垂直居中
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.GREEN);
canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getCurrentTextColor());
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float textWidth = mPaint.measureText(TEXT, 0, TEXT.length());
canvas.drawText(getText().toString(), (getWidth() - textWidth)/2f, getHeight()/2f, mPaint);
}
可以看到,文字相对于中线明显上偏了,那么偏移了多少呢,或者说文字往上偏移了多少呢? 我们如果能够计算出这个偏移量,绘制纵坐标的值设置为(这个偏移量 + 控件高度的一半),那么文字在垂直方向就居中了。如图:
可以得出偏移量的计算公式:
offset = (bottom - top)/2 - bottom
那么,要实现文字垂直居中就好办了:
@Override protected void onDraw(Canvas canvas) { //super.onDraw(canvas); //绘制水平中线,测试文字垂直居中 mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.GREEN); canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, mPaint); mPaint.setStyle(Paint.Style.FILL); mPaint.setTextSize(getTextSize()); mPaint.setColor(getCurrentTextColor()); Paint.FontMetrics fontMetrics = mPaint.getFontMetrics(); float textWidth = mPaint.measureText(TEXT, 0, TEXT.length()); float offset = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom; canvas.drawText(getText().toString(), (getWidth() - textWidth)/2f, getHeight()/2f + offset, mPaint); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。