Текст в Центре Android на холсте
Я пытаюсь отобразить текст, используя приведенный ниже код. Проблема в том, что текст не центрирован по горизонтали. Когда я устанавливаю координаты для 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);
}
Переведено автоматически
Ответ 1
Попробуйте следующее:
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);
Ответ 2
Расположите по центру с помощью 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.Выровнять.ПО ЛЕВОМУ КРАЮ? Вам все равно придется вычислять опорную точку.
Paint.descent() имеет тот недостаток, что он не учитывает реальный текст. Paint.descent() извлекает одно и то же значение, независимо от того, содержит ли текст буквы со спусками или нет. Вот почему я использую r.bottom вместо этого.
У меня возникли некоторые проблемы с Canvas.getHeight(), если API < 16. Вот почему я использую Canvas.getClipBounds(Rect) вместо этого. (Не используйте Canvas.getClipBounds().getHeight() поскольку он выделяет память для прямоугольника.)
Из соображений производительности вам следует выделять объекты до их использования в onDraw(). Поскольку drawCenter() будет вызываться внутри onDraw(), объект Rect r здесь предварительно выделен как поле.
Я попытался поместить код двух лучших ответов в свой собственный код (август 2015 г.) и сделал скриншот для сравнения результатов:
Текст должен располагаться по центру внутри прямоугольника с красной заливкой. Мой код создает белый текст, два других кода создают полностью серый текст (на самом деле они одинаковые, перекрывающиеся). Серый текст немного слишком низко и на два больше справа.
Вот как я сделал тест:
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);
}
}
Ответ 3
Выровнять текст по вертикали сложно, потому что текст опускался и поднимался, многие ребята использовали Paint.getTextBounds() для получения TextWidth и TextHeight , но это не сильно увеличивает центр текста. Здесь мы можем использовать Paint.measureText() для вычисления ширины текста, высоту текста мы просто вычитаем с уменьшением и подъемом, тогда мы получим максимально приближенный размер текста, следующая работа довольно проста друг для друга.
// 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);
Кстати, мы настоятельно рекомендуем использовать RectF вместо Rect, потому что для позиций нужны более точные значения, по моему опыту, RectF делает отклонение сверху и снизу всего на один пиксель на устройстве xhdpi, Rect было бы на два больше.
Ответ 4
Ваш код рисует центр базовой линии текста в центре представления. Чтобы расположить текст по центру в некоторой точке 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);
}