文字绘制和图片绘制的区别
我们绘制一张图片,一条直线,或一个矩形时
基本上确定上下左右的坐标,就确定了图片或几何元素的位置
但字体元素,由于其特殊的格式,并非从左往右,从上到下直接绘制的
字体格式的专业规范
Android中的FontMetric
Android中的FontMetric即是对以上字体规范的一种实现
在Android中,文字的绘制是从baseline位置开始的,它的y值为0
我们来看看FontMetric中各个字段代表的含义
- baseline,基线,文字绘制的起始位置
- ascent,上倾,基线到文字最高处的距离,为负数
- descent,下倾斜,基线到文字最低处的距离
- leading,行距,与上行文字的间隔
- top,文字最高处坐标,等于ascent
- bottom,文字最低处坐标,等于descent
- height,文字总高度,ascent、descent、等于leading绝对值的总和
Android居中绘制文字
由于文字是从baseline开始绘制的,而一般我们是不知道baseline的值的,就需要自己去计算
height = baseline + descent - ascent + leading; //行高,文字包括行距的高度
middle = baseline + ascent/2; //以ascent的中心作为文字中心,比较美观
当我们知道了文字顶部坐标,底部坐标,或中间坐标时
根据以上两个公式,就可以推算出baseline的值,很简单
工具类封装
以下是常用方法的封装,但这个工具类有点旧了,并非严格准确
正确的方法是按以上两个公式推算,偷懒的就用下面的工具类吧
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.text.TextPaint;
import android.view.Gravity;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import com.easing.commons.android.helper.exception.BizException;
import com.easing.commons.android.value.color.Colors;
@SuppressWarnings("all")
public class CanvasPainter {
//获取文字宽度
public static float getTextWidth(Paint paint, String text) {
float width = paint.measureText(text);
return width;
}
//获取文字高度
public static float getTextHeight(Paint paint) {
float height = (paint.getTextSize() + 0.00000007F) / 0.7535F;
return height;
}
//获取文字水平中心位置
public static float getTextCenterX(TextView textView, String text) {
TextPaint paint = textView.getPaint();
float textWidth = getTextWidth(paint, text);
int gravity = textView.getGravity();
if ((gravity & Gravity.LEFT) == Gravity.LEFT)
return textView.getPaddingLeft() + textWidth / 2;
if ((gravity & Gravity.RIGHT) == Gravity.RIGHT)
return textView.getMeasuredWidth() - textView.getPaddingRight() - textWidth / 2;
if ((gravity & Gravity.CENTER_HORIZONTAL) == Gravity.CENTER_HORIZONTAL)
return textView.getPaddingLeft() + (textView.getMeasuredWidth() - textView.getPaddingLeft() - textView.getPaddingRight()) / 2;
throw BizException.of("unknown horizontal alignment");
}
//获取文字竖直中心位置
public static float getTextCenterY(TextView textView) {
TextPaint paint = textView.getPaint();
float textHeight = getTextHeight(paint);
int gravity = textView.getGravity();
if ((gravity & Gravity.TOP) == Gravity.TOP)
return textView.getPaddingTop() + textHeight / 2;
if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM)
return textView.getMeasuredHeight() - textView.getPaddingBottom() - textHeight / 2;
if ((gravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL)
return textView.getPaddingTop() + (textView.getMeasuredHeight() - textView.getPaddingTop() - textView.getPaddingBottom()) / 2;
throw BizException.of("unknown vertical alignment");
}
//从中间开始绘制文字
public static void drawTextFromCenter(Canvas canvas, Paint paint, String text, Number centerX, Number centerY) {
float textWidth = getTextWidth(paint, text);
Paint.FontMetrics metrics = paint.getFontMetrics();
canvas.drawText(text, 0, text.length(), centerX.floatValue() - textWidth / 2, centerY.floatValue() - (metrics.ascent + metrics.descent) / 2, paint);
}
//从左下角开始绘制文字
public static void drawTextFromLeftBottom(Canvas canvas, Paint paint, String text, Number left, Number bottom) {
float textHeight = getTextHeight(paint);
Paint.FontMetrics metrics = paint.getFontMetrics();
canvas.drawText(text, 0, text.length(), left.floatValue(), bottom.floatValue() - textHeight / 2 - (metrics.ascent + metrics.descent) / 2, paint);
}
//从左上角开始绘制文字
public static void drawTextFromLeftTop(Canvas canvas, Paint paint, String text, Number left, Number top) {
float textHeight = getTextHeight(paint);
Paint.FontMetrics metrics = paint.getFontMetrics();
canvas.drawText(text, 0, text.length(), left.floatValue(), top.floatValue() + textHeight / 2 - (metrics.ascent + metrics.descent) / 2, paint);
}
//从顶部中间开始绘制文字
public static void drawTextFromTopCenter(Canvas canvas, Paint paint, String text, Number centerX, Number top) {
float textWidth = getTextWidth(paint, text);
float textHeight = getTextHeight(paint);
Paint.FontMetrics metrics = paint.getFontMetrics();
canvas.drawText(text, 0, text.length(), centerX.floatValue() - textWidth / 2, top.floatValue() + textHeight / 2 - (metrics.ascent + metrics.descent) / 2, paint);
}
//从底部中间开始绘制文字
public static void drawTextFromBottomCenter(Canvas canvas, Paint paint, String text, Number centerX, Number bottom) {
float textWidth = getTextWidth(paint, text);
float textHeight = getTextHeight(paint);
Paint.FontMetrics metrics = paint.getFontMetrics();
canvas.drawText(text, 0, text.length(), centerX.floatValue() - textWidth / 2, bottom.floatValue() - textHeight / 2 - (metrics.ascent + metrics.descent) / 2, paint);
}
//画矩形色块
public static void drawColorRect(Canvas canvas, Number left, Number top, Number right, Number bottom, @ColorRes int colorId) {
canvas.save();
canvas.clipRect(new Rect(left.intValue(), top.intValue(), right.intValue(), bottom.intValue()));
canvas.drawColor(Colors.getColor(colorId));
canvas.restore();
}
//画直线
public static void drawLine(Canvas canvas, Paint paint, Number left, Number top, Number right, Number bottom) {
canvas.drawLine(left.intValue(), top.intValue(), right.intValue(), bottom.intValue(), paint);
}
//画矩形
public static void drawRect(Canvas canvas, Paint paint, Number left, Number top, Number right, Number bottom) {
canvas.drawRect(left.intValue(), top.intValue(), right.intValue(), bottom.intValue(), paint);
}
}