Android TextView drawText BaseLine理解
解决问题:如何设置绘制文本在盒子中 垂直居中
1. getHeight/2 设置为 drawText 绘制坐标,不能居中
上代码XML:
Java代码:
package com.denganzhi.cusomerwidget.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2020/3/14.
*/
public class MyView extends View {
public MyView(Context context) {
super(context);
}
Paint paint=null;
Context context;
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context=context;
//设置画笔
paint=new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(80);
paint.setTypeface(Typeface.DEFAULT_BOLD); // 设置粗体
paint.setAntiAlias(true); // 消除锯齿
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int pxW = dip2px(context,100);
int pxH = dip2px(context,100);
//pxW:200
Log.e("denganzhi","pxW:"+pxW);
// canvas 画板,背景色
canvas.drawColor(Color.GREEN);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
// 这些坐标都是现对于baseLine的,top和ascent 是负数,在baseline的上面
// bottom 、descent 是正数
float top=fontMetrics.top;
float bottom= fontMetrics.bottom;
float asscent= fontMetrics.ascent;
float descent=fontMetrics.descent;
// top:-84.49219 bottom:21.679688 asscent:-74.21875descent:19.53125 Y100
Log.e("denganzhi","top:"+top+" bottom:"+bottom+ " asscent:"+asscent+ "descent:"+descent +" centerY"+ getHeight()/2);
// 画笔, 这个坐标是左下角的坐标,错误计算方法,baseLine 盒子 中心点,文字不能居中
canvas.drawText("g我f",10,pxH/2,paint);
// float newBaseLineY= getHeight()/2 + (( bottom-top)/2 - bottom);
String drawStr="g我f";
// X 轴居中
//获取文本的宽度,和上面类似,但是是一个比较粗略的结果
float measureText = paint.measureText(drawStr);
Log.e("denganzhi1", "measureText="+measureText);
// X 轴居中,盒子/2-文字宽度的/2 坐标开始绘制 文本
float newBaseLineX = getWidth()/2 - measureText/2;
// canvas.drawText(drawStr,newBaseLineX,newBaseLineY,paint);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
文字未能垂直居中
分析: 文本绘制最坐标是getHeight()/2, baseline,文字在水平中心轴的上方,如果要实现文字水平居中,那么往下移动
正确代码:
float top=fontMetrics.top;
float bottom= fontMetrics.bottom;
float asscent= fontMetrics.ascent;
float descent=fontMetrics.descent;
float newBaseLineY= getHeight()/2 + (( bottom-top)/2 - bottom);
float newBaseLineX = getWidth()/2 - measureText/2;
package com.denganzhi.cusomerwidget.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2020/3/14.
*/
public class MyView extends View {
public MyView(Context context) {
super(context);
}
Paint paint=null;
Context context;
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context=context;
//设置画笔
paint=new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(80);
paint.setTypeface(Typeface.DEFAULT_BOLD); // 设置粗体
paint.setAntiAlias(true); // 消除锯齿
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int pxW = dip2px(context,100);
int pxH = dip2px(context,100);
//pxW:200
Log.e("denganzhi","pxW:"+pxW);
// canvas 画板,背景色
canvas.drawColor(Color.GREEN);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
// 这些坐标都是现对于baseLine的,top和ascent 是负数,在baseline的上面
// bottom 、descent 是正数
float top=fontMetrics.top;
float bottom= fontMetrics.bottom;
float asscent= fontMetrics.ascent;
float descent=fontMetrics.descent;
// top:-84.49219 bottom:21.679688 asscent:-74.21875descent:19.53125 Y100
Log.e("denganzhi","top:"+top+" bottom:"+bottom+ " asscent:"+asscent+ "descent:"+descent +" centerY"+ getHeight()/2);
// 画笔, 这个坐标是左下角的坐标,错误计算方法,baseLine 盒子 中心点,文字不能居中
// canvas.drawText("g我f",10,pxH/2,paint);
float newBaseLineY= getHeight()/2 + (( bottom-top)/2 - bottom);
String drawStr="g我f";
// X 轴居中
//获取文本的宽度,和上面类似,但是是一个比较粗略的结果
float measureText = paint.measureText(drawStr);
Log.e("denganzhi1", "measureText="+measureText);
// X 轴居中,盒子/2-文字宽度的/2 坐标开始绘制 文本
float newBaseLineX = getWidth()/2 - measureText/2;
canvas.drawText(drawStr,newBaseLineX,newBaseLineY,paint);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
输出效果:
pxW:200
top:-84.49219 bottom:21.679688 asscent:-74.21875descent:19.53125 centerY100
measureText=155.0
效果分析: