Texte Android Center sur canvas

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 de drawText , il définit le bas du texte à cette position. Je voudrais que le texte soit dessiné pour que le texte soit centré aussi horizontalement.

Ceci est une image pour afficher mon problème plus loin:

Capture d'écran

 @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 () :

entrer la description de l'image ici

 private Rect r = new Rect(); private void drawCenter(Canvas canvas, Paint paint, Ssortingng 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 sharepoint référence du texte est centré verticalement. Le sharepoint référence est toujours sur la ligne de base. Alors, pourquoi ne pas utiliser Paint.Align.LEFT ? Vous devez calculer le sharepoint référence quand même.

  • Paint.descent () a l’inconvénient de ne pas prendre en compte 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 plutôt r.bottom .

  • J’ai eu quelques problèmes avec Canvas.getHeight () si API <16. C'est pourquoi j'utilise Canvas.getClipBounds (Rect) à la place. (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 objects avant qu’ils ne soient utilisés dans onDraw () . Comme drawCenter () sera appelé dans onDraw (), l’object Rect r est pré-alloué en tant que champ ici.


J’ai essayé de mettre le code des deux meilleures réponses dans mon propre code (août 2015) et j’ai fait une capture d’écran pour comparer les résultats:

texte centré trois versions

Le texte doit être centré dans le rectangle rempli en rouge. Mon code produit le texte en blanc, les deux autres codes produisent le texte en gris (ils sont en fait identiques, se chevauchant). Le texte gris est un peu trop bas et deux beaucoup à 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 Ssortingng 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, Ssortingng 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, Ssortingng 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, Ssortingng 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 car la descente et l’ascension du texte ont eu lieu, beaucoup de gars ont utilisé Paint.getTextBounds () pour récupérer TextWidth et TextHeight, mais cela ne rend pas le centre de texte très présent. Ici, nous pouvons utiliser Paint.measureText () pour calculer la TextWidth, le TextHeight que nous faisons simplement en soustrayant avec la descente et la montée, puis nous avons obtenu l’approche la plus proche de TextSize, le travail suivant est assez facile l’un pour l’autre.

 // 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); Ssortingng 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); 

capture d'écran par le code

Soit dit en passant, nous recommandons fortement d’utiliser RectF plutôt que Rect car les positions ont besoin de valeurs plus précises, selon mon expérience, RectF a fait les écarts en haut et en bas d’un pixel sur le périphérique xhdpi, Rect en serait deux de plus.

Votre code dessine le centre de la ligne de base du texte, au centre de la vue. Pour centrer le texte à un moment donné, x, y, vous devez calculer le centre du texte et le mettre au point.

Cette méthode dessine le texte centré au point x, y. Si vous passez le centre de votre vue, il dessine le texte centré.

 private void drawTextCentered(Ssortingng 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 cela:

  public static void drawCenterText(Ssortingng 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 mesortingcs = paint.getFontMesortingcs(); float acent = Math.abs(mesortingcs.ascent); float descent = Math.abs(mesortingcs.descent); y = rectF.centerY() + (acent - descent) / 2f; canvas.drawText(text, x, y, paint); Log.e("ghui", "top:" + mesortingcs.top + ",ascent:" + mesortingcs.ascent + ",dscent:" + mesortingcs.descent + ",leading:" + mesortingcs.leading + ",bottom" + mesortingcs.bottom); } 

rectF est la zone que vous voulez dessiner le texte, ça y est. Détails

Si nous utilisons la 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