We draw the ruble sign in the Android application

  • Tutorial
Recently, developers are increasingly tasked with using the ruble symbol in the text. However, the ruble symbol was approved relatively recently , the symbol received its code in the Unicode standard even later . Naturally, the Roboto headset on current platforms does not yet contain the ruble sign.

Idea

Create a headset consisting of one ruble symbol with the code U + 20BD , and use this headset when drawing text for ruble symbols.

A bit about Span

Android has a mechanism for marking strings with special objects that affect the rendering of TextView text. For example, there are objects for overriding the fill / background color , style, or everything at once (a full list of markers built into Android). About this mechanism already wrote on a habr here and here .

Create the right headset

For the basis of the future headset, I took a ready-made solution from Artemy Lebedev, which was written about some time ago on Habré. This headset consists of various styles of the ruble symbol assigned to the Latin alphabet characters (from lowercase a to s ).

List of all glyphs

I chose the glyph that is assigned to the letter i ( Ruble symbol). It seems to me that it is most suitable for use with a Roboto headset.
To edit the headset, I used the wonderful Glyphs application . I deleted all the glyphs from the headset and left only the selected one. I assigned him the code U + 20BD. The next step is to export to ttf.
In the end, it turned out like this .
Of course, it would be possible to edit the glyph of the capital P by completing the wand, however, I do not feel confident in this matter. It hurts a lot of nuances. If someone can do this, I will gladly accept your pull request.

Implementation

First, create a project from the template. I used the template with Blank Activity from the Android Studio suite, activity called MainActivity.
The markup for MainActivity looks like this:



Everything is simple here, create a LinearLayout with one descendant of EditText. We set the hint property of EditText with namespace toolsso that the tooltip is displayed only in the preview. In the program, we will set the prompt programmatically.

In MainActivity#onCreatewe need to compose a spanned string in which all the ruble signs will be marked with TypefaceSpan , which allows you to change the headset to draw the given characters. Here we are in for a little trouble: TypefaceSpan can only be created with font-family - the name of the font from the system set. Fortunately, judging by the TypefaceSpan source code, this approach is not conditional on the technical capabilities of the text rendering system, which allows us to create our own version of TypefaceSpan, which supports setting the headset directly to the Typeface object .

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);
    }
}


It remains only to mark the text using the TypefaceSpan2 announced above, with the required headset.

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);
    }
}


Here we load the template for our line containing the ruble symbol and a headset with a ruble glyph.
Then create a SpannableStringBuilder based on the template and use setSpan to set the markers for changing the headset.

Assign hint,

priceInput.setHint(resultSpan); 

and done!
Finished result

Link to source

Also popular now: