verticalmente vertical texto horizontalmente horizontal div centro centrar centrado bootstrap alinear java android canvas drawtext

java - horizontalmente - ¿Cómo alinear texto verticalmente?



centrar texto vertical y horizontal css (7)

Objetivo: Android> = 1.6 en un lienzo puro.

Supongamos que quiero escribir una función que dibuje un rectángulo rojo grande (ancho, alto) y luego dibuje un texto negro Hello World dentro. Quiero que el texto esté visualmente en el centro del rectángulo. Entonces intentemos:

void drawHelloRectangle(Canvas c, int topLeftX, int topLeftY, int width, int height) { Paint mPaint = new Paint(); // height of ''Hello World''; height*0.7 looks good int fontHeight = (int)(height*0.7); mPaint.setColor(COLOR_RED); mPaint.setStyle(Style.FILL); c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint); mPaint.setTextSize(fontHeight); mPaint.setColor(COLOR_BLACK); mPaint.setTextAlign(Align.CENTER); c.drawText( "Hello World", topLeftX+width/2, ????, mPaint); }

Ahora no sé qué poner en el argumento de drawText marcado por ???? , es decir, no sé cómo alinear verticalmente el texto.

Algo como

???? = topLeftY + height / 2 + fontHeight / 2 - fontHeight / 8;

parece funcionar más o menos bien, pero debe haber una mejor manera.


Ejemplo para centrarse en cx y cy :

private final Rect textBounds = new Rect(); //don''t new this up in a draw method public void drawTextCentred(Canvas canvas, Paint paint, String text, float cx, float cy){ paint.getTextBounds(text, 0, text.length(), textBounds); canvas.drawText(text, cx - textBounds.exactCenterX(), cy - textBounds.exactCenterY(), paint); }

¿Por qué la height()/2f funciona igual?

exactCentre() = (top + bottom) / 2f .

height()/2f = (bottom - top) / 2f

Estos solo arrojarían el mismo resultado cuando top es 0 . Este puede ser el caso para algunas fuentes en todos los tamaños, u otras fuentes en algunos tamaños, pero no para todas las fuentes en todos los tamaños.


Basado en la respuesta de steelbytes, el código actualizado se vería así:

void drawHelloRectangle(Canvas c, int topLeftX, int topLeftY, int width, int height) { Paint mPaint = new Paint(); // height of ''Hello World''; height*0.7 looks good int fontHeight = (int)(height*0.7); mPaint.setColor(COLOR_RED); mPaint.setStyle(Style.FILL); c.drawRect( topLeftX, topLeftY, topLeftX+width, topLeftY+height, mPaint); mPaint.setTextSize(fontHeight); mPaint.setColor(COLOR_BLACK); mPaint.setTextAlign(Align.CENTER); String textToDraw = new String("Hello World"); Rect bounds = new Rect(); mPaint.getTextBounds(textToDraw, 0, textToDraw.length(), bounds); c.drawText(textToDraw, topLeftX+width/2, topLeftY+height/2+(bounds.bottom-bounds.top)/2, mPaint); }


Como dibujar texto en Y significa que la línea base del texto terminará en Y píxeles hacia abajo desde el origen, lo que debe hacer cuando quiere centrar el texto dentro de un rectángulo de dimensiones (width, height) es:

paint.setTextAlign(Paint.Align.CENTER); // centers horizontally canvas.drawText(text, width / 2, (height - paint.ascent()) / 2, paint);

Tenga en cuenta que el ascenso es negativo (lo que explica el signo menos).

Esto no tiene en cuenta el descenso, que generalmente es lo que desea (el ascenso generalmente es la altura de los límites superiores a la línea de base).


Me tropecé con esta pregunta al tratar de resolver mi problema, y ​​la respuesta de @ Weston funciona bien conmigo.

En caso de Kotlin:

private fun drawText(canvas: Canvas) { paint.textSize = 80f val text = "Hello!" val textBounds = Rect() paint.getTextBounds(text, 0, text.length, textBounds); canvas.drawText(text, cx- textBounds.exactCenterX(), cy - textBounds.exactCenterY(), paint); //in case of another Rect as a container: //canvas.drawText(text, containerRect.exactCenterX()- textBounds.exactCenterX(), containerRect.exactCenterY() - textBounds.exactCenterY(), paint); }


Usando mPaint.getTextBounds () puedes preguntar qué tan grande será el texto cuando se dibuje, luego usar esa información puedes calcular dónde quieres dibujarlo.


public static PointF getTextCenterToDraw(String text, RectF region, Paint paint) { Rect textBounds = new Rect(); paint.getTextBounds(text, 0, text.length(), textBounds); float x = region.centerX() - textBounds.width() * 0.4f; float y = region.centerY() + textBounds.height() * 0.4f; return new PointF(x, y); }

Uso:

PointF p = getTextCenterToDraw(text, rect, paint); canvas.drawText(text, p.x, p.y, paint);


textY = topLeftY + height/2 - (mPaint.descent() + mPaint.ascent()) / 2

La distancia desde "línea base" a "centro" debe ser -(mPaint.descent() + mPaint.ascent()) / 2