web-dev-qa-db-fra.com

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 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:

 Screenshot

@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);
}
158
Sebastian

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);
329
Arun George

Centrer avec Paint.getTextBounds ():

 enter image description here

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:

 text centered three versions

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);
    }
}
168
andreas1724

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

screen shot by the code

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.

57
VinceStyling

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);
}
13
Borislav Markov

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
Daniel

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

1
ghui zhang

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:

 enter image description here 

1
Serg Burlaka

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

1
free_style

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 

0
JSONParser