Intereting Posts
Класс IntentService не запускает AsyncTask в главной теме. Вызов метода должен быть вызван из основного потока, в настоящее время выбранный поток является рабочим Как сделать HTTP-запрос с помощью файлов cookie на Android? Как преобразовать кучу кучи в формате android в формат eclipse RelativeLayout добавляет правило «RelativeLayout.LEFT_OF» не работает Новый выход на вызов Android Espresso: у ViewPager нет экземпляра адаптера Google map v2 Пользовательская информация с двумя кнопками мыши или ImageView Android – перетаскивание – переименование списка Android Terminal-IDE: ошибка терминала-gcc: arm-eabi-gcc не найден API Android Android v2 с настраиваемыми маркерами Экран эмулятора Android заполняет только часть доли фактического экрана эмулятора Android. Как динамически генерировать исходный идентификатор ресурса в android? CoordinatorLayout аварийно завершает работу приложения с IndexOutOfBoundsException Как сделать только чтение (программно заполнено) Предпочтения? Как получить дату из виджета DatePicker в Android?

Измерение высоты текста на Canvas (Android)

Любой прямой способ измерения высоты текста? То, как я это делаю сейчас, – это использовать measureText() для получения ширины, а затем путем проб и ошибок найти значение, чтобы получить приблизительную высоту. Я также возился с FontMetrics , но все это похоже на приближенные методы, которые сосут.

Я пытаюсь масштабировать вещи для разных резолюций. Я могу это сделать, но в итоге я получаю невероятно подробный код с большим количеством вычислений, чтобы определить относительные размеры. Я ненавижу это! Там должен быть лучший путь.

Solutions Collecting From Web of "Измерение высоты текста на Canvas (Android)"

Как насчет Paint.getTextBounds ()

Ответ @ bramp верен – частично, поскольку он не упоминает, что вычисленные границы будут минимальным прямоугольником, который полностью содержит текст с неявными начальными координатами 0, 0.

Это означает, что высота, например, «Py», будет отличаться от высоты «py» или «hi» или «oi» или «aw», потому что по пикселям они требуют разной высоты.

Это никоим образом не эквивалентно FontMetrics в классическом java.

Хотя ширина текста не сильно боль, высота есть.

В частности, если вам нужно вертикально центрировать выровненный текст, попробуйте получить границы текста «a» (без кавычек), вместо того, чтобы использовать текст, который вы собираетесь нарисовать. Работает на меня…

Вот что я имею в виду:

 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); paint.setStyle(Paint.Style.FILL); paint.setColor(color); paint.setTextAlign(Paint.Align.CENTER); paint.setTextSize(textSize); Rect bounds = new Rect(); paint.getTextBounds("a", 0, 1, bounds); buffer.drawText(this.myText, canvasWidth >> 1, (canvasHeight + bounds.height()) >> 1, paint); // remember x >> 1 is equivalent to x / 2, but works much much faster 

Вертикальное выравнивание по центру текста означает, что вертикальный центр выравнивает ограничивающий прямоугольник, который отличается для разных текстов (кепки, длинные буквы и т. Д.). Но то, что мы на самом деле хотим сделать, это также выровнять исходные тексты визуализированных текстов, чтобы они не выглядели повышенными или рифлеными. Итак, до тех пор, пока мы знаем центр наименьшей буквы (например, «a»), мы можем повторно использовать его выравнивание для остальных текстов. Это позволит центрировать все тексты, а также выравнивание по исходным линиям.

Существуют различные способы измерения высоты в зависимости от того, что вам нужно.

getTextBounds

Если вы делаете что-то вроде центрирования небольшого количества фиксированного текста, вы, вероятно, хотите getTextBounds . Вы можете получить ограничивающий прямоугольник таким образом

 Rect bounds = new Rect(); mTextPaint.getTextBounds(mText, 0, mText.length(), bounds); int height = bounds.height(); 

Как видно из следующих изображений, разные строки будут иметь разную высоту (показаны красным цветом).

Введите описание изображения здесь

Эти разные высоты могут быть недостатком в некоторых ситуациях, когда вам просто нужна постоянная высота независимо от текста. См. Следующий раздел.

Paint.FontMetrics

Вы можете рассчитать высоту шрифта из метрик шрифта. Высота всегда одна и та же, потому что она получена из шрифта, а не какой-либо конкретной текстовой строки.

 Paint.FontMetrics fm = mTextPaint.getFontMetrics(); float height = fm.descent - fm.ascent; 

Базой является строка, в которой находится текст. Спуск, как правило, самый дальний персонаж будет идти ниже линии, и восхождение, как правило, самый дальний персонаж будет проходить выше линии. Чтобы получить высоту, вы должны вычесть подъем, потому что это отрицательное значение. (Базовая линия равна y=0 а y уменьшает экран.)

Посмотрите на следующее изображение. Высота для обеих строк составляет 234.375 .

Введите описание изображения здесь

Если вам нужна высота линии, а не только высота текста, вы можете сделать следующее:

 float height = fm.bottom - fm.top + fm.leading; // 265.4297 

Это bottom и top части линии. Ведущий (интерлайн-интервал) обычно равен нулю, но вы должны добавить его в любом случае.

Изображения, приведенные выше, взяты из этого проекта . Вы можете поиграть с ним, чтобы увидеть, как работают показатели шрифтов.

StaticLayout

Для измерения высоты многострочного текста вы должны использовать StaticLayout . Я говорил об этом в деталях в этом ответе , но основной способ получить эту высоту выглядит так:

 String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text."; TextPaint myTextPaint = new TextPaint(); myTextPaint.setAntiAlias(true); myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density); myTextPaint.setColor(0xFF000000); int width = 200; Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL; float spacingMultiplier = 1; float spacingAddition = 0; boolean includePadding = false; StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding); float height = myStaticLayout.getHeight(); 

Высота – это размер текста, который вы указали в переменной Paint.

Другой способ узнать высоту

 mPaint.getTextSize(); 

Вы можете просто получить размер текста для объекта Paint с помощью метода getTextSize (). Например:

 Paint mTextPaint = new Paint (Paint.ANTI_ALIAS_FLAG); //use densityMultiplier to take into account different pixel densities final float densityMultiplier = getContext().getResources() .getDisplayMetrics().density; mTextPaint.setTextSize(24.0f*densityMultiplier); //... float size = mTextPaint.getTextSize(); 

Вы можете использовать класс android.text.StaticLayout чтобы указать необходимые границы, а затем вызвать getHeight() . Вы можете нарисовать текст (содержащийся в макете), вызвав метод draw(Canvas) .

Вы должны использовать Rect.width() и Rect.Height() которые возвращаются из getTextBounds() . Это подходит для меня.

Если у кого-то еще есть проблемы, это мой код.

У меня есть пользовательский вид, который является квадратным (width = height), и я хочу назначить ему символ. onDraw() показывает, как получить высоту персонажа, хотя я его не использую. Символ будет отображаться посередине.

 public class SideBarPointer extends View { private static final String TAG = "SideBarPointer"; private Context context; private String label = ""; private int width; private int height; public SideBarPointer(Context context) { super(context); this.context = context; init(); } public SideBarPointer(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; init(); } public SideBarPointer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; init(); } private void init() { // setBackgroundColor(0x64FF0000); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ super.onMeasure(widthMeasureSpec, heightMeasureSpec); height = this.getMeasuredHeight(); width = this.getMeasuredWidth(); setMeasuredDimension(width, width); } protected void onDraw(Canvas canvas) { float mDensity = context.getResources().getDisplayMetrics().density; float mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity; Paint previewPaint = new Paint(); previewPaint.setColor(0x0C2727); previewPaint.setAlpha(200); previewPaint.setAntiAlias(true); Paint previewTextPaint = new Paint(); previewTextPaint.setColor(Color.WHITE); previewTextPaint.setAntiAlias(true); previewTextPaint.setTextSize(90 * mScaledDensity); previewTextPaint.setShadowLayer(5, 1, 2, Color.argb(255, 87, 87, 87)); float previewTextWidth = previewTextPaint.measureText(label); // float previewTextHeight = previewTextPaint.descent() - previewTextPaint.ascent(); RectF previewRect = new RectF(0, 0, width, width); canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint); canvas.drawText(label, (width - previewTextWidth)/2, previewRect.top - previewTextPaint.ascent(), previewTextPaint); super.onDraw(canvas); } public void setLabel(String label) { this.label = label; Log.e(TAG, "Label: " + label); this.invalidate(); } }