понедельник, 16 января 2012 г.

Точное расстояние между строками текста

Как ни странно, но рассположить один под другим две строки текста с точным расстояние между ними - это нетривиальная задача. Происходит это из-за того, что внутри TextView текст немного смещен вниз. Это легко можно увидить, если установить для него контрастный бекграунд.
XML разметка для данного примера выглядит так:
<TextView
    android:text="Test text. Igy."
    android:textSize="18sp"
    android:textColor="#F000"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:background="#6F00"/>
Это дополнительное расстояние используется для размещения диакритических надстрочных знаков (акцентов) и в английском языке никак не задействованно. Поэтому, если приложение ориентировано на англоговорящий рынок, то возникает желание отключить использование дополнительного смещения. Обычное решение, которое рекомендуют для этого - это установить свойство android:includeFontPadding в значение false. Тогда текст будет выглядить так:
<TextView
    android:text="Test text. Igy."
    android:textSize="18sp"
    android:textColor="#F000"
    android:includeFontPadding="false"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:background="#6F00"/>
На первый взгляд ситуация улучшилась. Но со второго взгляда становится видно, что верхнее смещение все еще довольно большое и, более того, оказался отрезанным самый низ буквы "g". Это ошибка специфичная для Android 2.3, соотественно сейчас она проявляется на половине устройств.
Таким образом, если в интерфейсе расстояние между двумя строками текста запланировано, в 20dp, то используемое смещение надо будет вычислить и оно будет меньше 20dp. Для быстрого вычисления я составил таблицу смещений в относительных еденицах. Если есть две строки размером 18sp между которыми нужно установить расстояние в 10dp, то надо из 10dp вычесть верхнее и нижнее смещение для 18sp и получить реальное смещение всего лишь в 3dp.

Пока составлял таблицу, то с удивлением увидел, что реальная высота букв для 15sp и 16sp в hdpi разрешение одна и та же, отличается только расстояние между соседними буквами.

2 комментария:

  1. Текст не смещен вниз.
    Просто дело в том что при отрисовке текста есть такой параметр как BaseLine.
    И именно он указывает где будут находится точни в строке. Соотетственно и текст будет как-бы выше и ниже него - на чуть-чуть ниже - чтобы отрисовать всякие хвостики в g, q, p и.д. и выше - для отрисовки собственно букв.

    ОтветитьУдалить
    Ответы
    1. По правилам отображения шрифта текст действительно не смещен вниз. Но он смещен вниз визуально.
      Андроид позволяет выравнивать два элемента UI по горизонтали используя свойство layout_alignBaseline. Но, если мы отображаем два текстовых поля одно под другим, то оперировать baseLine мы не можем и нам приходится либо смириться с визуальным разрывом между полями либо постараться его компенсировать. Сделать компенсацию можно не во всех языках, но для английского языка задача решаема. Вариант решения я привел в этом посте.

      Удалить