Android Center texte sur toile

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 élaboré afin que le texte est centré aussi horizontalement.

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

Capture

@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);
}
155
demandé sur Pang 2012-06-20 17:13:15

8 réponses

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);
315
répondu Arun George 2013-05-12 00:37:19

Centre avec Peinture.getTextBounds():

entrez la description de l'image ici

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);
}
  • De la Peinture.Aligner.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 Peinture.Aligner.Gauche ? Vous devez calculer le point de référence de toute façon.

  • De la Peinture.descente() a l'inconvénient, qu'il ne considère pas le vrai texte. Peinture.descente() 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 de avec Toile.getHeight () si API Canvas.getClipBounds (Rect) à la place. (Ne pas utiliser Toile.getClipBounds ().getHeight () {[4] } car il alloue de la mémoire pour un Rect .)

  • Pour des raisons de performance, vous devez allouer des objets avant ils sont utilisés dans onDraw () . Comme drawCenter() sera appelée à l'intérieur de onDraw() l'objet Rect r est préaffectés comme un champ ici.


J'ai essayé de mettre le code des deux premières réponses dans mon propre code (août 2015) et fait une capture d'écran de comparer les résultats:

texte centré trois versions

Le texte doit être centré dans le rectangle rouge rempli. Mon code produit le texte blanc, les deux autres codes produisent tout à fait le texte gris (ils sont en fait les mêmes, qui se chevauchent). Le texte Gris est un peu trop bas et deux beaucoup sur la 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);
    }
}
148
répondu andreas1724 2017-05-23 11:54:58

Aligner verticalement est difficile parce que la descente et l'ascension du texte se sont produites, beaucoup de gars ont utilisé Paint.getTextBounds () pour récupérer les TextWidth et TextHeight, mais cela ne rend pas beaucoup le centre de texte. Ici, nous pouvons utiliser Peinture.measureText () pour calculer le TextWidth, le TextHeight nous faisons simplement la soustraction avec la descente et l'ascension, puis nous avons obtenu le plus D'approche 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);

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

capture d'écran par le code

Au fait, nous recommande fortement l'utilisation RectF plutôt que Rect parce que les positions ont besoin de valeurs plus précises, dans mon expérience, RectF fait la déviation supérieure et inférieure juste un pixel sur le périphérique xhdpi, Rect serait deux de plus.

57
répondu VinceStyling 2015-05-23 02:53:14

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 mettre que au point.

Cette méthode dessinera le texte centré au point x, Y. Si vous lui passez le centre de votre vue, elle dessinera le texte 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);
}
11
répondu Borislav Markov 2016-07-17 00:27:35

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);    `
3
répondu Daniel 2015-07-02 13:52:33

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 que vous voulez dessiner le texte, C'est tout. Détails

1
répondu ghui zhang 2015-10-22 16:48:12

Si nous utilisons la mise en page statique

mStaticLayout = new StaticLayout(mText, mTextPaint, mTextWidth,
                Layout.Alignment.ALIGN_CENTER, 1.0f, 0, true);

Mise en page.Alignement.ALIGN_CENTER cela fera l'affaire. La mise en page statique a également beaucoup d'autres avantages.

Référence: Documentation Android

1
répondu free_style 2017-12-05 20:56:13

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, veuillez me le faire savoir

0
répondu JSONParser 2018-10-02 08:22:37