14

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.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
naz
  • 1,478
  • 2
  • 21
  • 32

6 Answers6

22

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

Community
  • 1
  • 1
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • 1
    Thanks for the great answer! I tried it but it gave me chinese characters? – naz Apr 12 '13 at 07:14
  • Yeah, you'll have to use a font that includes small caps characters for this to work. Typically an OpenType font. – Kevin Coppock Apr 12 '13 at 07:20
  • how do I view the uf000 code? If I have a font what tool can I use? Can't search because I don't know what the keyword to use. thanks – naz Apr 12 '13 at 08:30
  • If you're on Windows you can use Character Map. (Start > Run... > "charmap") – Kevin Coppock Apr 12 '13 at 16:07
  • 1
    That helped. I am looking for a calibri alternative with small caps in it. I've tried droid, open sans and others but didn't seem to make it work. With the font you are using it is working. Your input pointed me to the right direction. Thanks – naz Apr 13 '13 at 05:40
  • 2
    These unicode code points are all in the PRIVATE_USE_AREA. Presumably, they are entirely specific to whatever font you are using. The actual codepoint for small capital characters is very different. Eg. ᴀ is '\u1D00' – lhunath Aug 22 '13 at 17:49
  • 1
    @lhunath That may be the case for the font you're using, and yes, these are in the private use area, but conventially this is the location in most professional fonts, it seems (at least from my limited experimentation). The screenshots here show that with Chaparral (and some other pro fonts I had), the private use unicode characters I provided do work. – Kevin Coppock Aug 22 '13 at 21:41
  • @kcoppock When I say "the actual codepoint", I don't mean "the codepoint for my font", I mean "the codepoint as defined by the unicode standard". So, that's not for the font I'm using. http://www.unicode.org/charts/PDF/U1D00.pdf – lhunath Aug 23 '13 at 23:00
  • @lhunath Those appear to be for foreign languages (you'll notice there is only a subset of small capital characters in that list). Most fonts do not include all true Small Caps characters. – Kevin Coppock Aug 24 '13 at 00:01
7

Apologies for dragging up a very old question.

I liked @kcoppock's approach to this, but unfortunately the font I'm using is missing the small-cap characters. I suspect many others will find themselves in this situation.

That inspired me to write a little util method that will take a mixed-case string (e.g. Small Caps) and create a formatted spannable string that looks like Sᴍᴀʟʟ Cᴀᴘs but only uses the standard A-Z characters.

  • It works with any font that has the A-Z characters - nothing special required
  • It is easily useable in a TextView (or any other text-based view, for that matter)
  • It doesn't require any HTML
  • It doesn't require any editing of your original strings

I've posed the code here: https://gist.github.com/markormesher/3e912622d339af01d24e

Mark Ormesher
  • 2,289
  • 3
  • 27
  • 35
0

Found an alternative here Is it possible to have multiple styles inside a TextView?

Basically you can use html tags formatting the size of the characters and give a small caps effect....

Community
  • 1
  • 1
naz
  • 1,478
  • 2
  • 21
  • 32
0

Just call this getSmallCaps(text) function:

public SpannableStringBuilder getSmallCaps(String text) {

    text = text.toUpperCase();
    text = text.trim();
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
    if (text.contains(" ")) {
        String[] arr = text.split(" ");
        for (int i = 0; i < arr.length; i++) {
            spannableStringBuilder.append(getSpannableStringSmallCaps(arr[i]));
            spannableStringBuilder.append(" ");
        }
    } else {
        spannableStringBuilder=getSpannableStringSmallCaps(text);
    }
    return spannableStringBuilder;
}


public SpannableStringBuilder getSpannableStringSmallCaps(String text) {

    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(
            text);
    spannableStringBuilder.setSpan(new AbsoluteSizeSpan(36), 0, 1, 0);
    spannableStringBuilder.setSpan(new StyleSpan(Typeface.BOLD), 0, 1, 0);
    spannableStringBuilder.setSpan(new StyleSpan(Typeface.BOLD), 1,
            text.length(), 0);
    return spannableStringBuilder;
}
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Jitendra Singh
  • 149
  • 2
  • 7
0

This is not my code but its works perfectly.

 public SpannableString getSmallCapsString(String input) {
    // values needed to record start/end points of blocks of lowercase letters
    char[] chars = input.toCharArray();
    int currentBlock = 0;
    int[] blockStarts = new int[chars.length];
    int[] blockEnds = new int[chars.length];
    boolean blockOpen = false;

    // record where blocks of lowercase letters start/end
    for (int i = 0; i < chars.length; ++i) {
        char c = chars[i];
        if (c >= 'a' && c <= 'z') {
            if (!blockOpen) {
                blockOpen = true;
                blockStarts[currentBlock] = i;
            }
            // replace with uppercase letters
            chars[i] = (char) (c - 'a' + '\u0041');
        } else {
            if (blockOpen) {
                blockOpen = false;
                blockEnds[currentBlock] = i;
                ++currentBlock;
            }
        }
    }

    // add the string end, in case the last character is a lowercase letter
    blockEnds[currentBlock] = chars.length;

    // shrink the blocks found above
    SpannableString output = new SpannableString(String.valueOf(chars));
    for (int i = 0; i < Math.min(blockStarts.length, blockEnds.length); ++i) {
        output.setSpan(new RelativeSizeSpan(0.8f), blockStarts[i], blockEnds[i], Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
    }

    return output;
}

Example:

SpannableString setStringObj = getSmallCapsStringTwo("Object"); tvObj.setText(setStringObj);
Péter Hidvégi
  • 743
  • 6
  • 21
-2

in XML edit text has property :android:capitalize=""

deepak825
  • 432
  • 2
  • 8