В последнее время перед разработчиками все чаще ставится задача использовать символ рубля в тексте. Однако, символ рубля был утвержден относительно недавно, символ получил свой код в стандате 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 (

Для редактирования гарнитуры, я использовал замечательное приложение 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);
и готово!

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