Android Canvas.DrawText文本绘制

更新时间:2022-01-23

1. 先来一个简单的演示效果

在这里插入图片描述

1)MyDrawTextView.java

自定义的View,代码如下

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

public class MyDrawTextView extends AppCompatTextView {
    public MyDrawTextView(@NonNull Context context) {
        super(context);
    }

    public MyDrawTextView(@NonNull Context context, 
    	@Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyDrawTextView(@NonNull Context context, 
    	@Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";
        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.RED);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);
    }
}

2)MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
    }
}

3)activity_main.xml

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.mydrawtexttest.MyDrawTextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</RelativeLayout>

2. 展开具体来说说

1)Canvas.drawText 的方法参数

Android Developers 中描述的 Canvas.drawText方法,参考文档:地址

public void drawText(@NonNull String text, float x, float y, 
	@NonNull Paint paint) {
    super.drawText(text, x, y, paint);
}
Canvas.drawText参数描述
text需要绘制的文本内容
x正在绘制的文本原点的 x 坐标
y正在绘制的文本基线baseLine的 y 坐标
paintPaint

2)Paint的方法

Android Developers 中描述的 Paint的方法,参考文档:地址

Paint的方法描述
paint.setStyle填充方式,默认FILL填充,还有STROKE描边,FILL_AND_STROKE填充并描边
paint.setTextSize文本大小,以像素为单位
paint.setTextAlign设置对齐方式
paint.getFontSpacing获取行间距

3)演示1 左对齐

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

4)演示2 左对齐并向右偏移

关于中间的分割线,可以参考这个博文:DrawLine

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.RED);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing();
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

5)演示3 居中对齐

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.RED);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing();
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.CENTER); // 居中对齐,默认值LEFT
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing() * 2;
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

6)演示4 右对齐

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.RED);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing();
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.CENTER); // 居中对齐,默认值LEFT
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing() * 2;
        canvas.drawText(text, x, baseLine, paint);

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.RIGHT); // 右对齐,默认值LEFT
        paint.setColor(Color.GRAY);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2;
        baseLine = 100 + paint.getFontSpacing() * 3;
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

7)演示5 上下左右居中对齐

a)错误演示效果:

这里并没有上下左右居中对齐,有微差的。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.CENTER); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = getWidth() / 2;
        float baseLine = 50 + getHeight() / 2;
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

b)Paint的方法
Paint的方法描述
paint.measureText测量文本的宽度
Paint.FontMetrics描述
ascent单行距文本基线上方的推荐距离。注意:是 的值
descent单行距文本基线下方的推荐距离。注意:是正的值
leading建议在文本行之间添加额外空间。
bottom给定文本大小下字体中最低字形基线下方的最大距离。
top给定文本大小的字体中最高字形基线上方的最大距离。

在这里插入图片描述

c)正确的演示效果:
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    String text = "绘制文本";

    Paint paint = new Paint();
    paint.setTextSize(100); // 文字大小
    paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
    paint.setColor(Color.BLUE);
    paint.setAntiAlias(true); // 防锯齿
    paint.setDither(true);    // 防抖动

    // 当默认左对齐的情况下
    // 仅仅getWidth() / 2 ,文字会出现在中间的右方,如演示2的效果
    // 当 减去文本宽度的一半时,即向左平移了文本的一半,正好左右居中了
    float x = getWidth() / 2 - paint.measureText(text) / 2;

    // 再来解决上下居中
    // getHeight() / 2 这样设置的话,baseLine就是正好中间上方的位置,需要再向下平移一部分
    // getFontMetrics() 可以获取到 accent、descent,如截图中的标识部分
    // descent为正的,ascent为负的,他们相加 再 除以2,正好是需要向下偏移的距离
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();
    float baseLine = getHeight() / 2 - (fontMetrics.descent + fontMetrics.ascent)/2;
    canvas.drawText(text, x, baseLine, paint);
}

在这里插入图片描述

3. 图层 保存和恢复

canvas.save() 可以进行保存当前canvas的状态, 保存后再进行平移等操作。

canvas.restore() 恢复到上次保存时的状态,相当于回滚了,save和restore之间的操作给扔弃了。

canvas.scale() 在X轴/Y轴上进行缩放

public void scale(float sx, float sy) {
    if (sx == 1.0f && sy == 1.0f) return;
    nScale(mNativeCanvasWrapper, sx, sy);
}
canvas.scale参数描述
x在 X 轴方向上进行缩放
y在 Y 轴方向上进行缩放

1)演示:不进行缩放的效果

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

//        canvas.save();

    String text = "绘制文本";

    Paint paint = new Paint();
    paint.setTextSize(100); // 文字大小
    paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
    paint.setColor(Color.BLUE);
    paint.setAntiAlias(true); // 防锯齿
    paint.setDither(true);    // 防抖动
    float x = 0;
    float baseLine = 100;
    canvas.drawText(text, x, baseLine, paint);

//        canvas.scale(0.5f, 0.5f);

//        canvas.restore();

    paint.setTextSize(100); // 文字大小
    paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
    paint.setColor(Color.RED);
    paint.setAntiAlias(true); // 防锯齿
    paint.setDither(true);    // 防抖动
    x = getWidth() / 2 - paint.measureText(text) / 2;
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();
    baseLine = getHeight() / 2 - (fontMetrics.descent + fontMetrics.ascent)/2;
    canvas.drawText(text, x, baseLine, paint);
}

在这里插入图片描述

2)演示:进行缩放的效果

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

//        canvas.save();

        String text = "绘制文本";

        Paint paint = new Paint();
        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        float x = 0;
        float baseLine = 100;
        canvas.drawText(text, x, baseLine, paint);

        canvas.scale(0.5f, 0.5f);

//        canvas.restore();

        paint.setTextSize(100); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(Color.RED);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动
        x = getWidth() / 2 - paint.measureText(text) / 2;
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        baseLine = getHeight() / 2 - (fontMetrics.descent + fontMetrics.ascent)/2;
        canvas.drawText(text, x, baseLine, paint);
    }

在这里插入图片描述

3)演示:进行缩放 并 save及restore 的效果

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // 先进行保存
    canvas.save();

    String text = "绘制文本";

    Paint paint = new Paint();
    paint.setTextSize(100); // 文字大小
    paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
    paint.setColor(Color.BLUE);
    paint.setAntiAlias(true); // 防锯齿
    paint.setDither(true);    // 防抖动
    float x = 0;
    float baseLine = 100;
    canvas.drawText(text, x, baseLine, paint);

    // 缩小
    canvas.scale(0.5f, 0.5f);

    // 恢复
    canvas.restore();

    paint.setTextSize(100); // 文字大小
    paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
    paint.setColor(Color.RED);
    paint.setAntiAlias(true); // 防锯齿
    paint.setDither(true);    // 防抖动
    x = getWidth() / 2 - paint.measureText(text) / 2;
    Paint.FontMetrics fontMetrics = paint.getFontMetrics();
    baseLine = getHeight() / 2 - (fontMetrics.descent + fontMetrics.ascent)/2;
    canvas.drawText(text, x, baseLine, paint);
}

在这里插入图片描述

4. 文字变色效果

1) MyDrawTextView2.java

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

public class MyDrawTextView2 extends AppCompatTextView {
    private float progess = 0.01f;

    public MyDrawTextView2(@NonNull Context context) {
        super(context);
    }

    public MyDrawTextView2(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyDrawTextView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        myDraw(canvas, 0, (int) (getWidth() * progess), Color.BLUE);
        myDraw(canvas, (int) (getWidth() * progess), getWidth(), Color.RED);
    }

    private void myDraw(Canvas canvas, int left, int right, int colorValue) {
        canvas.save();

        Rect rect = new Rect(left, 0, right, getHeight());
        canvas.clipRect(rect);

        Paint paint = new Paint();
        paint.setTextSize(getTextSize()); // 文字大小
        paint.setTextAlign(Paint.Align.LEFT); // 默认值LEFT
        paint.setColor(colorValue);
        paint.setAntiAlias(true); // 防锯齿
        paint.setDither(true);    // 防抖动

        String text = getText().toString();
        if (TextUtils.isEmpty(text)) return;

        float dx = 0;
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
        float baseLine = getHeight() / 2 + dy;
        canvas.drawText(text, dx, baseLine, paint);

        canvas.restore();
    }

    public void setProgress(float progress) {
        this.progess = progress;
        // 重新绘制
        invalidate();
    }
}

2) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    
    <com.example.mydrawtexttest.MyDrawTextView2
        android:layout_alignParentBottom="true"
        android:id="@+id/my_draw_text_view2_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello world"
        android:textSize="30sp"
        />

    <Button
        android:id="@+id/change_id"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="change"
        />
</RelativeLayout>

3) MainActivity.java


import androidx.appcompat.app.AppCompatActivity;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.view.View;
import android.view.Window;

public class MainActivity extends AppCompatActivity {

    private MyDrawTextView2 myDrawTextView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        myDrawTextView2 = findViewById(R.id.my_draw_text_view2_id);

        findViewById(R.id.change_id).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setAnimation();
            }
        });
    }

    public void setAnimation() {
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(2000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float animatedValue = (Float) animation.getAnimatedValue();
                myDrawTextView2.setProgress(animatedValue);
            }
        });
        valueAnimator.start();
    }
}

4) 效果

在这里插入图片描述

示例源码地址:

    MyDrawTextView

参考文档:

DrawLine博客文档:地址

Canvas.clipRect裁剪矩形 博客文档:地址

Android Developers 中描述的 Canvas.drawText方法,参考文档:地址

Android Developers 中描述的 Paint的方法,参考文档:地址

Android Developers 中描述的 Canvas.scale方法,参考文档:地址

日进一步!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值