J'essaie d'afficher un texte en utilisant le code ci-dessous . Le problème est que le texte n'est pas centré horizontalement . Lorsque je définis les coordonnées pour drawText
, le bas du texte est placé à cette position. Je voudrais que le texte soit dessiné de manière à ce que le texte soit centré également horizontalement.
Ceci est une image pour afficher mon problème plus loin:
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//canvas.drawRGB(2, 2, 200);
Paint textPaint = new Paint();
textPaint.setARGB(200, 254, 0, 0);
textPaint.setTextAlign(Align.CENTER);
textPaint.setTypeface(font);
textPaint.setTextSize(300);
canvas.drawText("Hello", canvas.getWidth()/2, canvas.getHeight()/2 , textPaint);
}
Essayez ce qui suit:
int xPos = (canvas.getWidth() / 2);
int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() + textPaint.ascent()) / 2)) ;
//((textPaint.descent() + textPaint.ascent()) / 2) is the distance from the baseline to the center.
canvas.drawText("Hello", xPos, yPos, textPaint);
Centrer avec Paint.getTextBounds ():
private Rect r = new Rect();
private void drawCenter(Canvas canvas, Paint paint, String text) {
canvas.getClipBounds(r);
int cHeight = r.height();
int cWidth = r.width();
Paint.setTextAlign(Paint.Align.LEFT);
Paint.getTextBounds(text, 0, text.length(), r);
float x = cWidth / 2f - r.width() / 2f - r.left;
float y = cHeight / 2f + r.height() / 2f - r.bottom;
canvas.drawText(text, x, y, Paint);
}
Paint.Align.CENTER ne signifie pas que le point de référence du texte est centré verticalement. Le point de référence est toujours sur la ligne de base. Alors, pourquoi ne pas utiliser Paint.Align.LEFT? Vous devez quand même calculer le point de référence.
Paint.descent () a le désavantage de ne pas considérer le texte réel. Paint.descent () récupère la même valeur, que le texte contienne ou non des lettres avec des descentes. C'est pourquoi j'utilise r.bottom à la place.
J'ai eu quelques problèmes avec Canvas.getHeight () si API <16. C'est pourquoi j'utilise plutôt Canvas.getClipBounds (Rect). (N'utilisez pas Canvas.getClipBounds (). GetHeight () car il alloue de la mémoire pour un Rect.)
Pour des raisons de performances, vous devez allouer des objets avant qu'ils ne soient utilisés dans onDraw (). Comme drawCenter () sera appelé dans onDraw (), l'objet Rect r est préalloué sous forme de champ ici.
J'ai essayé de mettre le code des deux principales réponses dans mon propre code (août 2015) et j'ai fait une capture d'écran pour comparer les résultats:
Le texte doit être centré dans le rectangle rempli de rouge. Mon code produit le texte en blanc, les deux autres codes produisent tous le texte en gris (ils sont en fait les mêmes, ils se chevauchent). Le texte en gris est un peu trop bas et deux très à droite.
Voici comment j'ai fait le test:
import Android.app.Activity;
import Android.content.Context;
import Android.content.pm.ActivityInfo;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.Paint;
import Android.graphics.Rect;
import Android.graphics.RectF;
import Android.graphics.Typeface;
import Android.os.Bundle;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.FrameLayout;
class MyView extends View {
private static String LABEL = "long";
private static float TEXT_HEIGHT_RATIO = 0.82f;
private FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(0, 0);
private Rect r = new Rect();
private Paint paint = new Paint();
private Paint rectPaint = new Paint();
public MyView(Context context) {
super(context);
}
private void drawTextBounds(Canvas canvas, Rect rect, int x, int y) {
rectPaint.setColor(Color.rgb(0, 0, 0));
rectPaint.setStyle(Paint.Style.STROKE);
rectPaint.setStrokeWidth(3f);
rect.offset(x, y);
canvas.drawRect(rect, rectPaint);
}
// andreas1724 (white color):
private void draw1(Canvas canvas, Paint paint, String text) {
Paint.setTextAlign(Paint.Align.LEFT);
Paint.setColor(Color.rgb(255, 255, 255));
canvas.getClipBounds(r);
int cHeight = r.height();
int cWidth = r.width();
Paint.getTextBounds(text, 0, text.length(), r);
float x = cWidth / 2f - r.width() / 2f - r.left;
float y = cHeight / 2f + r.height() / 2f - r.bottom;
canvas.drawText(text, x, y, Paint);
drawTextBounds(canvas, r, (int) x, (int) y);
}
// Arun George (light green color):
private void draw2(Canvas canvas, Paint textPaint, String text) {
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setColor(Color.argb(100, 0, 255, 0));
int xPos = (canvas.getWidth() / 2);
int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() + textPaint.ascent()) / 2));
canvas.drawText(text, xPos, yPos, textPaint);
}
// VinceStyling (light blue color):
private void draw3(Canvas yourCanvas, Paint mPaint, String pageTitle) {
mPaint.setTextAlign(Paint.Align.LEFT);
mPaint.setColor(Color.argb(100, 0, 0, 255));
r = yourCanvas.getClipBounds();
RectF bounds = new RectF(r);
bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
bounds.bottom = mPaint.descent() - mPaint.ascent();
bounds.left += (r.width() - bounds.right) / 2.0f;
bounds.top += (r.height() - bounds.bottom) / 2.0f;
yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int margin = 10;
int width = w - 2 * margin;
int height = h - 2 * margin;
params.width = width;
params.height = height;
params.leftMargin = margin;
params.topMargin = margin;
setLayoutParams(params);
Paint.setTextSize(height * TEXT_HEIGHT_RATIO);
Paint.setAntiAlias(true);
Paint.setTypeface(Typeface.create(Typeface.SERIF, Typeface.BOLD_ITALIC));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.rgb(255, 0, 0));
draw1(canvas, Paint, LABEL);
draw2(canvas, Paint, LABEL);
draw3(canvas, Paint, LABEL);
}
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
FrameLayout container = new FrameLayout(this);
container.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
container.addView(new MyView(this));
setContentView(container);
}
}
Aligner verticalement est difficile parce que la descente et l'ascension de texte ont eu lieu, beaucoup de gars ont utilisé Paint.getTextBounds () pour récupérer TextWidth et TextHeight, mais cela ne centre pas vraiment le texte. Ici, nous pouvons utiliser Paint.measureText () pour calculer TextWidth, TextHeight que nous faisons simplement en soustrayant avec descente et ascension, puis nous avons obtenu le plus d’approche TextSize.
// the Paint instance(should be assign as a field of class).
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(getResources().getDimension(R.dimen.btn_textsize));
// the display area.
Rect areaRect = new Rect(0, 0, 240, 60);
// draw the background style (pure color or image)
mPaint.setColor(Color.BLACK);
yourCanvas.drawRect(areaRect, mPaint);
String pageTitle = "文字小说";
RectF bounds = new RectF(areaRect);
// measure text width
bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
// measure text height
bounds.bottom = mPaint.descent() - mPaint.ascent();
bounds.left += (areaRect.width() - bounds.right) / 2.0f;
bounds.top += (areaRect.height() - bounds.bottom) / 2.0f;
mPaint.setColor(Color.WHITE);
yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);
En passant, nous vous recommandons vivement d’utiliser RectF plutôt que Rect car les positions ont besoin de valeurs plus précises. Selon mon expérience, RectF a réduit l’écart en haut et en bas d’un pixel sur un périphérique xhdpi, Rect en étant deux.
Votre code dessine le centre de la ligne de base du texte, au centre de la vue. Afin de centrer le texte à un moment donné, x, y, vous devez calculer le centre du texte et mettre that au point.
Cette méthode dessine le texte centré au point x, y. Si vous passez au centre de votre vue, le texte sera centré.
private void drawTextCentered(String text, int x, int y, Paint paint, Canvas canvas) {
int xPos = x - (int)(Paint.measureText(text)/2);
int yPos = (int) (y - ((textPaint.descent() + textPaint.ascent()) / 2)) ;
canvas.drawText(text, xPos, yPos, textPaint);
}
Je trouve que la meilleure solution pour centrer le texte est la suivante:
textPaint.setTextAlign(Paint.Align.CENTER);
//textPaint is the Paint object being used to draw the text (it must be initialized beforehand)
float textY=center.y;
float textX=center.x;
// in this case, center.x and center.y represent the coordinates of the center of the rectangle in which the text is being placed
canvas.drawText(text,textX,textY,textPaint); `
Je crée une méthode pour simplifier ceci:
public static void drawCenterText(String text, RectF rectF, Canvas canvas, Paint paint) {
Paint.Align align = Paint.getTextAlign();
float x;
float y;
//x
if (align == Paint.Align.LEFT) {
x = rectF.centerX() - Paint.measureText(text) / 2;
} else if (align == Paint.Align.CENTER) {
x = rectF.centerX();
} else {
x = rectF.centerX() + Paint.measureText(text) / 2;
}
//y
metrics = Paint.getFontMetrics();
float acent = Math.abs(metrics.ascent);
float descent = Math.abs(metrics.descent);
y = rectF.centerY() + (acent - descent) / 2f;
canvas.drawText(text, x, y, Paint);
Log.e("ghui", "top:" + metrics.top + ",ascent:" + metrics.ascent
+ ",dscent:" + metrics.descent + ",leading:" + metrics.leading + ",bottom" + metrics.bottom);
}
rectF est la zone dans laquelle vous voulez dessiner le texte, c’est ça . Détails
fonctionne pour moi à utiliser: textPaint.textAlign = Paint.Align.CENTER avec textPaint.getTextBounds
private fun drawNumber(i: Int, canvas: Canvas, translate: Float) {
val text = "$i"
textPaint.textAlign = Paint.Align.CENTER
textPaint.getTextBounds(text, 0, text.length, textBound)
canvas.drawText(
"$i",
translate + circleRadius,
(height / 2 + textBound.height() / 2).toFloat(),
textPaint
)
}
le résultat est:
Si nous utilisons une mise en page statique
mStaticLayout = new StaticLayout(mText, mTextPaint, mTextWidth,
Layout.Alignment.ALIGN_CENTER, 1.0f, 0, true);
Layout.Alignment.ALIGN_CENTER cela fera l'affaire. La disposition statique a également beaucoup d'autres avantages.
Référence: Documentation Android
Cela a fonctionné pour moi:
Paint.setTextAlign(Paint.Align.CENTER);
int xPos = (newWidth / 2);
int yPos = (newHeight / 2);
canvas.drawText("Hello", xPos, yPos, Paint);
si quelqu'un trouve un problème s'il vous plaît faites le moi savoir