215

以下のコードを使用してテキストを表示しようとしています。問題は、テキストが水平方向に中央揃えされていないことです。の座標を設定するとdrawText、この位置にテキストの下部が設定されます。テキストが水平方向にも中央揃えになるようにテキストを描画したいと思います。

これは、私の問題をさらに表示するための図です。

スクリーンショット

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

12 に答える 12

408

次のことを試してください。

 Paint textPaint = new Paint();
 textPaint.setTextAlign(Paint.Align.CENTER);

 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);
于 2012-06-20T14:31:44.823 に答える
244

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は、テキストの参照点が垂直方向の中央にあるという意味ではありません。基準点は常にベースライン上にあります。では、なぜPaint.Align.LEFTを使用しないのでしょうか? とにかく基準点を計算する必要があります。

  • Paint.descent()には、実際のテキストを考慮しないという欠点があります。Paint.descent()は、テキストに子孫のある文字が含まれているかどうかに関係なく、同じ値を取得します。そのため、代わりにr.bottomを使用します。

  • API < 16 の場合、 Canvas.getHeight()でいくつか問題が発生しました。そのため、代わりにCanvas.getClipBounds(Rect)を使用しています。( Canvas.getClipBounds().getHeight()はRectにメモリを割り当てるため、使用しないでください。)

  • パフォーマンス上の理由から、オブジェクトをonDraw()で使用する前に割り当てる必要があります。drawCenter ()はonDraw()内で呼び出されるため、オブジェクトRect rはここでフィールドとして事前に割り当てられます。


上位 2 つの回答のコードを自分のコード (2015 年 8 月) に入れようとし、スクリーンショットを作成して結果を比較しました。

テキスト中心の 3 つのバージョン

テキストは、赤く塗りつぶされた四角形の中央に配置する必要があります。私のコードは白いテキストを生成し、他の 2 つのコードは全体で灰色のテキストを生成します (実際には同じで、重なり合っています)。灰色のテキストは少し低すぎて、右に 2 つありすぎます。

これが私がテストを作成した方法です:

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);
    }
}
于 2015-08-18T19:40:18.637 に答える
17

コードは、テキストのベースラインの中心、ビューの中心を描画しています。テキストをあるポイント x、y の中央に配置するには、テキストの中央を計算し、それをポイントに配置する必要があります。

このメソッドは、点 x、y を中心にテキストを描画します。ビューの中心に渡すと、テキストが中央に描画されます。

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);
}
于 2016-07-16T20:34:02.470 に答える
2

これらを onDraw メソッドに追加します。

paint.setColor(getContext().getResources().getColor(R.color.black));
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("Text", (float) getHeight() / 2f, (float) getWidth() / 2f, paint);
于 2020-12-21T22:25:22.707 に答える
0

静的レイアウトを使用している場合

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

Layout.Alignment.ALIGN_CENTERこれでうまくいきます。静的レイアウトには他にも多くの利点があります。

参照: Android ドキュメント

于 2017-12-05T20:56:13.973 に答える