web-dev-qa-db-ja.com

Androidキャンバスの中央のテキスト

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

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

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

以下を試してください:

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

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

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

  • API <16の場合、いくつかの 問題 withCanvas.getHeight()があるため、Canvas.getClipBounds(Rect)代わりに。 (Canvas.getClipBounds()。getHeight()は、Rect。)

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


私は自分のコードに2つのトップアンサーのコードを入れようとし(2015年8月)、結果を比較するためのスクリーンショットを作成しました:

text centered three versions

テキストは、赤で塗りつぶされた長方形の中央に配置する必要があります。私のコードは白いテキストを生成し、他の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);
    }
}
179
andreas1724

テキストの下降と上昇が発生し、多くの人がPaint.getTextBounds()を使用してTextWidthとTextHeightを取得するため、垂直方向に整列するのは困難ですが、テキストをあまり中央に配置しません。ここでは、Paint.measureText()を使用してTextWidthを計算することができます。TextHeightは単純に下降と上昇で減算します。その後、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

ところで、RectではなくRectFを使用することを強くお勧めします。これは、私の経験では、RectFはxhdpiデバイスで1ピクセルだけ上下の偏差を行ったためです。 Rectはさらに2つあります。

60
VinceStyling

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

このメソッドは、ポイント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);
}
14
Borislav Markov

テキストをセンタリングするための最適なソリューションは次のとおりです。

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

これを単純化するメソッドを作成します。

    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は、テキストを描画する領域です。それだけです。 詳細

1
ghui zhang

私のために動作します:textPaint.textAlign = Paint.Align.CENTERwithtextPaint.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
            )
        }

結果は次のとおりです。

enter image description here

1
Serg Burlaka

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

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

Layout.Alignment.ALIGN_CENTERこれはトリックを行います。静的レイアウトには、他にも多くの利点があります。

リファレンス: Androidドキュメント

1
free_style

これは私のために働いた:

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

誰かが何か問題を見つけたら、私に知らせてください

0
JSONParser