Answers:
关于paint.getTextBounds()(对象方法)
根据您的需要,可以使用不同的方法来测量高度。
如果您要进行诸如将少量固定文本精确居中的操作,则可能需要getTextBounds
。您可以这样获得边界矩形
Rect bounds = new Rect();
mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);
int height = bounds.height();
如下面的图像所示,不同的字符串将给出不同的高度(以红色显示)。
在某些情况下,无论文本是什么,都只需要一个恒定的高度,这些不同的高度可能是不利的。请参阅下一节。
您可以根据字体指标计算字体的高度。高度始终是相同的,因为它是从字体而不是任何特定的文本字符串获得的。
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float height = fm.descent - fm.ascent;
基线是文本所在的行。下降通常是角色将在线条下方走得最远,而上升通常是角色将在线条上方走得最远。要获得高度,您必须减去上升,因为它是负值。(基线是y=0
并且y
减小了屏幕。)
看下图。两根琴弦的高度均为234.375
。
如果您想要行高而不是仅文本高度,则可以执行以下操作:
float height = fm.bottom - fm.top + fm.leading; // 265.4297
这是该行的bottom
和top
。前导(行间距)通常为零,但无论如何都应添加。
上面的图片来自这个项目。您可以使用它来查看字体指标的工作方式。
要测量多行文字的高度,应使用StaticLayout
。我在此答案中对此进行了详细讨论,但获得此高度的基本方法如下:
String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text.";
TextPaint myTextPaint = new TextPaint();
myTextPaint.setAntiAlias(true);
myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
myTextPaint.setColor(0xFF000000);
int width = 200;
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;
StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding);
float height = myStaticLayout.getHeight();
getTextSize()
字体大小以像素为单位(相对于sp
单位)。@androiddeveloper
@bramp的答案是正确的-部分原因是,它没有提到计算出的边界将是包含完全具有隐式起始坐标0,0的文本的最小矩形。
这意味着,例如“ Py”的高度将与“ py”或“ hi”或“ oi”或“ aw”的高度不同,因为在像素方面它们需要不同的高度。
这绝不等同于经典Java中的FontMetrics。
文字的宽度虽然不怎么麻烦,但高度却很。
特别是,如果您需要垂直对齐绘制的文本,请尝试获取文本“ a”的边界(不带引号),而不要使用要绘制的文本。为我工作...
这就是我的意思:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(textSize);
Rect bounds = new Rect();
paint.getTextBounds("a", 0, 1, bounds);
buffer.drawText(this.myText, canvasWidth >> 1, (canvasHeight + bounds.height()) >> 1, paint);
// remember x >> 1 is equivalent to x / 2, but works much much faster
垂直居中对齐文本表示垂直居中对齐边界矩形-不同的文本(大写字母,长字母等)不同。但是,我们实际上要做的是还要对齐渲染文本的基线,以使它们不会显得过高或粗糙。因此,只要我们知道最小字母的中心(例如“ a”),我们就可以将其对齐方式重新用于其余文本。这将使所有文本居中对齐并使其基线对齐。
x >> 1
好久没见了。仅为此
x / 2
并对其进行优化,以x >> 1
x / 2
考虑到克里斯的评论,@ keaukraine 在阅读代码时更加友好。
buffer
在这个例子吗?它canvas
传递给draw(Canvas)
方法了吗?
您可以使用getTextSize()方法简单地获取Paint对象的文本大小。例如:
Paint mTextPaint = new Paint (Paint.ANTI_ALIAS_FLAG);
//use densityMultiplier to take into account different pixel densities
final float densityMultiplier = getContext().getResources()
.getDisplayMetrics().density;
mTextPaint.setTextSize(24.0f*densityMultiplier);
//...
float size = mTextPaint.getTextSize();
24.0f
来的?
如果仍然有问题,这是我的代码。
我有一个自定义视图,该视图为正方形(宽度=高度),我想为其分配一个字符。onDraw()
展示了如何获得角色的身高,尽管我没有使用它。角色将显示在视图中间。
public class SideBarPointer extends View {
private static final String TAG = "SideBarPointer";
private Context context;
private String label = "";
private int width;
private int height;
public SideBarPointer(Context context) {
super(context);
this.context = context;
init();
}
public SideBarPointer(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public SideBarPointer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
private void init() {
// setBackgroundColor(0x64FF0000);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
height = this.getMeasuredHeight();
width = this.getMeasuredWidth();
setMeasuredDimension(width, width);
}
protected void onDraw(Canvas canvas) {
float mDensity = context.getResources().getDisplayMetrics().density;
float mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
Paint previewPaint = new Paint();
previewPaint.setColor(0x0C2727);
previewPaint.setAlpha(200);
previewPaint.setAntiAlias(true);
Paint previewTextPaint = new Paint();
previewTextPaint.setColor(Color.WHITE);
previewTextPaint.setAntiAlias(true);
previewTextPaint.setTextSize(90 * mScaledDensity);
previewTextPaint.setShadowLayer(5, 1, 2, Color.argb(255, 87, 87, 87));
float previewTextWidth = previewTextPaint.measureText(label);
// float previewTextHeight = previewTextPaint.descent() - previewTextPaint.ascent();
RectF previewRect = new RectF(0, 0, width, width);
canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint);
canvas.drawText(label, (width - previewTextWidth)/2, previewRect.top - previewTextPaint.ascent(), previewTextPaint);
super.onDraw(canvas);
}
public void setLabel(String label) {
this.label = label;
Log.e(TAG, "Label: " + label);
this.invalidate();
}
}