Размеры текста в канвасе

от
Android    canvas


Если вы рисуете графику прямо в Canvas'е, то рано или поздно вам захочется выводить на экран и текст. Для этого вам нужно знать, как он будет располагаться, соответственно потребуется рассчитать его ширину/высоту для выравнивания и прочих эффектных штук.



Недавно в своём приложении мне также понадобилось вертикальное и горизонтальное центрирование. Поэтому я начал со следующего кода:

  1. Paint mTextPaint = new Paint();
  2. mTextPaint.setTextAlign(Paint.Align.CENTER);  // Включим центрирование
  3.  
  4. // И когда происходит отрисовка...
  5. canvas.drawText(mText,
  6.         mBounds.centerX(),  // mBounds — некая область канваса
  7.         mBounds.centerY(),  // X, Y — центр области
  8.         mTextPaint
  9. );

Я не ожидал, что это сработает как надо (привычная ситуация), и вышло что-то в таком роде:

1.png

У нас есть метод!!
Тогда я попытался вычислить размеры текста и изменить координаты X, Y следующим образом:

  1. int mTextWidth, mTextHeight;
  2. Paint mTextPaint = new Paint();
  3.  
  4. // Вычислим размеры текста
  5. Rect textBounds = new Rect();
  6. mTextPaint.getTextBounds(mText, 0, mText.length(), textBounds);
  7. mTextWidth = textBounds.width();
  8. mTextHeight = textBounds.height();
  9.  
  10. canvas.drawText(mText,
  11.         mBounds.centerX() - (mTextWidth / 2f),
  12.         mBounds.centerY() + (mTextHeight / 2f),
  13.         mTextPaint
  14. );

Гораздо лучше, но всё ещё остался небольшой дефект, приглядитесь:

2.png

Чтобы убедиться, что с моими глазами всё в порядке, я добавил отображение прямоугольника, полученного с помощью метода Paint.getTextBounds().

3.png

Как можно видеть, текст чуть-чуть выходит за границы.

Ещё один метод
Именно в этот момент я заметил, что в классе Paint определён ещё один метод для вычисления ширины текста: Paint.measureText()

Он вычисляет только ширину, а не высоту, поэтому я попытался скомбинировать два метода:

  1. int mTextWidth, mTextHeight;
  2. Paint mTextPaint = new Paint();
  3.  
  4. Rect textBounds = new Rect();
  5. mTextPaint.getTextBounds(mText, 0, mText.length(), textBounds);
  6. mTextWidth = mTextPaint.measureText(mText);  // Используем measureText для ширины
  7. mTextHeight = textBounds.height();           // Возьмём высоту из getTextBounds()
  8.  
  9. // Выводим...
  10. canvas.drawText(mText,
  11.         mBounds.centerX() - (mTextWidth / 2f),
  12.         mBounds.centerY() + (mTextHeight / 2f),
  13.         mTextPaint
  14. );

И получаем идеально центрированный текст! Фуф.

4.png


Автор: Chris Banes