wake-up-neo.com

Android Center-Text auf Leinwand

Ich versuche, einen Text mit dem folgenden Code anzuzeigen .. Das Problem ist, dass der Text nicht horizontal zentriert ist. Wenn ich die Koordinaten für drawText setze, wird der Text unten an dieser Position festgelegt. Ich möchte, dass der Text so gezeichnet wird, dass der Text auch horizontal zentriert ist.

Dieses Bild zeigt mein Problem weiter an:

 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

Versuche Folgendes:

 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

Zentrieren mit 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 bedeutet nicht, dass der Bezugspunkt des Texts vertikal zentriert ist. Der Bezugspunkt liegt immer auf der Basislinie. Warum also nicht Paint.Align.LEFT verwenden? Sie müssen den Bezugspunkt trotzdem berechnen.

  • Paint.descent () hat den Nachteil, dass der echte Text nicht berücksichtigt wird. Paint.descent () ruft den gleichen Wert ab, unabhängig davon, ob der Text Buchstaben mit Abstieg enthält oder nicht. Deshalb benutze ich stattdessen r.bottom.

  • Ich hatte einige Probleme mit Canvas.getHeight (), wenn API <16. Deshalb verwende ich stattdessen Canvas.getClipBounds (Rect). (Verwenden Sie nicht Canvas.getClipBounds (). GetHeight (), da für Rect Speicher reserviert wird.)

  • Aus Performancegründen sollten Sie Objekte zuordnen, bevor sie in onDraw () verwendet werden. Da drawCenter () innerhalb von onDraw () aufgerufen wird, wird das Objekt Rect r hier als Feld vorbelegt. 


Ich habe versucht, den Code der beiden besten Antworten in meinen eigenen Code zu integrieren (August 2015) und machte einen Screenshot, um die Ergebnisse zu vergleichen:

 text centered three versions

Der Text sollte innerhalb des rot ausgefüllten Rechtecks ​​zentriert sein. Mein Code erzeugt den weißen Text, die anderen beiden Codes ergeben insgesamt den grauen Text (sie sind eigentlich gleich und überlappen sich). Der graue Text ist etwas zu niedrig und zwei rechts davon.

So habe ich den Test gemacht:

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

Die vertikale Ausrichtung ist schwierig, da Textabstieg und -aufstieg stattfanden. Viele Leute verwendeten Paint.getTextBounds () , um TextWidth und TextHeight abzurufen, aber der Text zentriert sich nicht sehr. Hier können wir Paint.measureText () verwenden, um die TextWidth zu berechnen, das TextHeight, das wir einfach mit Abstieg und Aufstieg subtrahieren, dann haben wir die meiste Annäherung an TextSize, die folgende Arbeit ist relativ einfach für einander.

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

Übrigens empfehlen wir dringend die Verwendung von RectF anstelle von Rect , da die Positionen genauere Werte erfordern. Nach meiner Erfahrung hat RectF die obere und untere Abweichung nur um ein Pixel auf einem xhdpi-Gerät vorgenommen, Rect wäre noch zwei weitere.

57
VinceStyling

Ihr Code zeichnet die Mitte der Grundlinie des Texts in der Mitte der Ansicht. Um den Text an einem bestimmten Punkt (x, y) zu zentrieren, müssen Sie die Mitte des Textes berechnen und that an den Punkt setzen.

Bei dieser Methode wird Text zentriert am Punkt x, y gezeichnet. Wenn Sie es in der Mitte der Ansicht übergeben, wird der Text zentriert gezeichnet.

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

Ich finde, dass die beste Lösung zum Zentrieren von Text wie folgt ist:

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

Ich erstelle eine Methode, um dies zu vereinfachen:

    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 ist der Bereich, in dem Sie den Text zeichnen möchten. Details

1
ghui zhang

funktioniert für mich zu verwenden: textPaint.textAlign = Paint.Align.CENTER mit 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
            )
        }

ergebnis ist:

 enter image description here 

1
Serg Burlaka

Wenn wir statisches Layout verwenden 

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

Layout.Alignment.ALIGN_CENTER Dies erledigt den Trick. Statisches Layout hat auch viele andere Vorteile.

Referenz: Android-Dokumentation

1
free_style

Das hat für mich funktioniert:

 Paint.setTextAlign(Paint.Align.CENTER);
        int xPos = (newWidth / 2);
        int yPos = (newHeight / 2);
        canvas.drawText("Hello", xPos, yPos, Paint);

wenn jemand ein Problem findet, lass es mich wissen 

0
JSONParser