Small Caps on TextViews, EditTexts, and Buttons in Android

naz picture naz · Apr 12, 2013 · Viewed 9k times · Source

Is there something I can do to make the text look in small caps/capital? As described here: http://en.wikipedia.org/wiki/Small_caps. I used a converter but some characters are missing.

Answer

Kevin Coppock picture Kevin Coppock · Apr 12, 2013

EDIT 2015-08-02: As of API 21 (Lollipop) you can simply add:

android:fontFeatureSettings="smcp"

to your TextView declaration in XML, or at runtime, invoke:

textView.setFontFeatureSettings("smcp");

Of course, this only works for API 21 and up, so you'd still have to handle the old solution manually until you are only supporting Lollipop and above.


Being a bit of a typography geek at heart, this seemed like a really good question. I got to learn some more about Unicode today, as well as an answer for your question. :)

First, you'll need to have a font that includes "actual" small-caps characters. I'm assuming you know that since you're asking, but typically most professional fonts include these. Unfortunately most professional fonts are not licensed for distribution, so you may not be able to use them in your application. Anyway, in the event that you do find one (I used Chaparral Pro as an example here), this is how you can get small caps.

From this answer I found that the small caps characters (for A-Z) are located starting at Unicode-UF761. So I built a mapping of these characters:

private static char[] smallCaps = new char[]
{
        '\uf761', //A
        '\uf762',
        '\uf763',
        '\uf764',
        '\uf765',
        '\uf766',
        '\uf767',
        '\uf768',
        '\uf769',
        '\uf76A',
        '\uf76B',
        '\uf76C',
        '\uf76D',
        '\uf76E',
        '\uf76F',
        '\uf770',
        '\uf771',
        '\uf772',
        '\uf773',
        '\uf774',
        '\uf775',
        '\uf776',
        '\uf777',
        '\uf778',
        '\uf779',
        '\uf77A'   //Z
};

Then added a helper method to convert an input string to one whose lowercase letters have been replaced by their Small Caps equivalents:

private static String getSmallCapsString (String input) {
    char[] chars = input.toCharArray();
    for(int i = 0; i < chars.length; i++) {
        if(chars[i] >= 'a' && chars[i] <= 'z') {
            chars[i] = smallCaps[chars[i] - 'a'];
        }
    }
    return String.valueOf(chars);
}

Then just use that anywhere:

String regularCase = "The quick brown fox jumps over the lazy dog.";
textView.setText(getSmallCapsString(regularCase));

For which I got the following result:

Example of Small Caps