当前位置:   article > 正文

10_android文字绘制_android ondraw 绘制文字

android ondraw 绘制文字

10_android文字绘制

一.概述

我们在使用TextView去显示一段文本时,如果遇到一些特殊情况,比如我们希望文本显示的时候并不局限于显示单一的颜色,而是希望显示渐变色,或者是在做一个类似酷狗、网易云音乐的歌词显示动画效果的时候,这个时候如果使用系统为我们提供的TextView并不能满足我们的要求,因此就需要我们自己去绘制文字。

二.自定义控件继承自TextView,在onDraw方法中绘制文字
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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
<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"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

只分析代码的话,此时文字应该会被绘制在左上角的位置,那么运行起来看一下:

在这里插入图片描述

实际上并没有,实际上可以看到只有字母’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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

可以看到,文字的显示出来了,但是并没有完全显示,那么,纵坐标的值应该取多少合适?

  • 首先,我们需要知道,我们通过canvas.drawText绘制文字时,传入的纵坐标的值并不是指文字的最顶端,而是文字的baseline的位置
  • 我们刚刚改变纵坐标的值,实际上就是改变baseline的位置

在这里插入图片描述

那么,结合上图,对于上面的情况,我们只需要将纵坐标的值设置为-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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

接下来,把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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 不指定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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

在这里插入图片描述

四.文字垂直居中

先试试把绘制的纵坐标设置为控件的高度/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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

可以看到,文字相对于中线明显上偏了,那么偏移了多少呢,或者说文字往上偏移了多少呢? 我们如果能够计算出这个偏移量,绘制纵坐标的值设置为(这个偏移量 + 控件高度的一半),那么文字在垂直方向就居中了。如图:

在这里插入图片描述

可以得出偏移量的计算公式:

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号