В последнее время перед разработчиками все чаще ставится задача использовать символ рубля в тексте. Однако, символ рубля был утвержден относительно недавно, символ получил свой код в стандате Unicode еще позже. Естественно, гарнитура Roboto на текущих платформах еще не содержит знака рубля.
Создать гарнитуру состоящую из одного символа рубля с кодом U+20BD, и при отрисовке текста для символов рубля использовать эту гарнитуру.
В ОС Android существует механизм маркировки строк специальными объектами влияющими на рендеринг текста TextView. Например, существуют объекты для переопределения цвета заливки/фона, стиля или всего сразу (полный список встроенных в Android маркеров). Об этом механизме уже писале на хабре здесь и здесь.
За основу будущей гарнитуры я взял готовое решение от Артемия Лебедева, о котором писали некоторое время назад на Хабре. Эта гарнитура состоит из различных начертаний символа рубля закрепленных за символами латинского алфавита (от строчной a до s).

Я выбрал глиф, котор��й закреплен за буквой i (
). Как мне кажется, он наиболее подходит для использования с гарнитурой Roboto.
Для редактирования гарнитуры, я использовал замечательное приложение Glyphs. Я удалил все глифы из гарнитуры и оставил только выбранный. Ему я назначил код U+20BD. Следующий шаг — экспорт в ttf.
В итоге у меня получилось так.
Конечно, можно было бы отредактировать глиф заглавной Р, дорисовав палочку, однако, я не чувствую в себе уверенности в этом деле. Уж больно много нюансов. Если кто-то может сделать это, с удовольствием приму ваш pull request.
Для начала создадим проект из шаблона. Я использовал шаблон с Blank Activity из комплекта Android Studio, activity назвал MainActivity.
Разметка для MainActivity выглядит так:
Тут все просто, создаем LinearLayout с одним потомком EditText. Свойство hint у EditText мы задаем с namespace
В
Осталось только сделать маркировку текста с помощью объявленного выше TypefaceSpan2, с необходимой нам гарнитурой.
Здесь мы загружаем шаблон нашей строки, содержащей символ рубля и гарнитуру с глифом рубля.
Затем создаем SpannableStringBuilder на основе шаблона и с помощью setSpan расставляем маркеры для смены гарнитуры.
Назначаем hint,
и готово!

Ссылка на исходники
Идея
Создать гарнитуру состоящую из одного символа рубля с кодом U+20BD, и при отрисовке текста для символов рубля использовать эту гарнитуру.
Немного о Span
В ОС Android существует механизм маркировки строк специальными объектами влияющими на рендеринг текста TextView. Например, существуют объекты для переопределения цвета заливки/фона, стиля или всего сразу (полный список встроенных в Android маркеров). Об этом механизме уже писале на хабре здесь и здесь.
Создание нужной гарнитуры
За основу будущей гарнитуры я взял готовое решение от Артемия Лебедева, о котором писали некоторое время назад на Хабре. Эта гарнитура состоит из различных начертаний символа рубля закрепленных за символами латинского алфавита (от строчной a до s).

Я выбрал глиф, котор��й закреплен за буквой i (
). Как мне кажется, он наиболее подходит для использования с гарнитурой Roboto.Для редактирования гарнитуры, я использовал замечательное приложение Glyphs. Я удалил все глифы из гарнитуры и оставил только выбранный. Ему я назначил код U+20BD. Следующий шаг — экспорт в ttf.
В итоге у меня получилось так.
Конечно, можно было бы отредактировать глиф заглавной Р, дорисовав палочку, однако, я не чувствую в себе уверенности в этом деле. Уж больно много нюансов. Если кто-то может сделать это, с удовольствием приму ваш pull request.
Реализация
Для начала создадим проект из шаблона. Я использовал шаблон с Blank Activity из комплекта Android Studio, activity назвал MainActivity.
Разметка для MainActivity выглядит так:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <EditText android:id="@+id/main_price_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" tools:hint="@string/main_price_hint" /> </LinearLayout>
Тут все просто, создаем LinearLayout с одним потомком EditText. Свойство hint у EditText мы задаем с namespace
tools, для того что бы подсказка отображалась только в предпросмотре. В программе мы будем задавать подсказку программно.В
MainActivity#onCreate мы должны составить spanned string, в котором все знаки рубля будут маркированны TypefaceSpan, который позволяет изменить гарнитуру для отрисовки заданных символов. Тут нас ожидает маленькая неприятность: TypefaceSpan можно создать только с font-family — названием шрифта из набора системы. К счастью, судя по исходному коду TypefaceSpan, этот подход не обусловлен техническими возможностями системы рендеринга текста, что позволяет нам создать собственную версию TypefaceSpan, который поддерживает задание гарнитуры непосредственно объектом Typeface. package me.pepyakin.roublesign; import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextPaint; import android.text.style.MetricAffectingSpan; public class TypefaceSpan2 extends MetricAffectingSpan { private final Typeface mTypeface; public TypefaceSpan2(Typeface typeface) { mTypeface = typeface; } @Override public void updateDrawState(TextPaint ds) { apply(ds, mTypeface); } @Override public void updateMeasureState(TextPaint paint) { apply(paint, mTypeface); } private static void apply(Paint paint, Typeface tf) { int oldStyle; Typeface old = paint.getTypeface(); if (old == null) { oldStyle = 0; } else { oldStyle = old.getStyle(); } int fake = oldStyle & ~tf.getStyle(); if ((fake & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fake & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(tf); } }
Осталось только сделать маркировку текста с помощью объявленного выше TypefaceSpan2, с необходимой нам гарнитурой.
String priceHint = getString(R.string.main_price_hint); final Typeface roubleSupportedTypeface = Typeface.createFromAsset(getAssets(), "fonts/rouble2.ttf"); SpannableStringBuilder resultSpan = new SpannableStringBuilder(priceHint); for (int i = 0; i < resultSpan.length(); i++) { if (resultSpan.charAt(i) == '\u20BD') { TypefaceSpan2 roubleTypefaceSpan = new TypefaceSpan2(roubleSupportedTypeface); resultSpan.setSpan(roubleTypefaceSpan, i, i + 1, 0); } }
Здесь мы загружаем шаблон нашей строки, содержащей символ рубля и гарнитуру с глифом рубля.
Затем создаем SpannableStringBuilder на основе шаблона и с помощью setSpan расставляем маркеры для смены гарнитуры.
Назначаем hint,
priceInput.setHint(resultSpan);
и готово!

Ссылка на исходники