在Android上的TextViews、EditTexts和Buttons中使用小型大写字母

14

欢迎来到 Stack Overflow http://stackoverflow.com/faq - Triode
1
你想为你的文本字段使用自定义字体吗? - Raghunandan
6个回答

22
编辑 2015-08-02: 从API 21 (棒棒糖) 开始,您可以简单地添加:
android:fontFeatureSettings="smcp"

在 XML 中添加 TextView 声明,或在运行时调用:

textView.setFontFeatureSettings("smcp");

当然,这仅适用于API 21及以上版本,因此您仍需要手动处理旧解决方案,直到只支持棒棒糖(Android 5.0)及以上版本。


作为一个内心有点儿字体极客的人,这个问题似乎很不错。今天我学到了更多关于Unicode的知识,并得到了你的问题的答案。:)

首先,您需要拥有一种包含“实际”小型大写字母字符的字体。我假设您知道这一点,但通常大多数专业字体都包含这些字符。不幸的是,大多数专业字体未经许可不得分发,因此您可能无法在应用程序中使用它们。无论如何,在您找到一种字体后,以下是如何获取小型大写字母的方法(我在这里以Chaparral Pro为例)。

这个答案中,我发现小型大写字母字符(A-Z)的Unicode编码从UF761开始。因此,我构建了这些字符的映射:

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

然后添加了一个辅助方法,将输入的字符串转换为小写字母已被其小型大写字母等效替代的字符串:

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

那么只需将其随处使用:

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

我得到了以下结果:

小型大写字母示例


1
谢谢你的好答案!我尝试了一下,但它给了我中文字符? - naz
1
那很有帮助。我正在寻找一种具有小型大写字母的Calibri替代品。我已经尝试了Droid、Open Sans和其他字体,但似乎都没有成功。使用您正在使用的字体可以解决问题。您的建议指引了我正确的方向。谢谢。 - naz
2
这些Unicode代码点都在PRIVATE_USE_AREA中。可以推测,它们完全是针对您使用的字体而设计的。小型大写字符的实际代码点非常不同。例如,ᴀ是'\u1D00'。 - lhunath
1
@lhunath,这可能是你使用的字体的情况,是的,这些字符位于专用区域,但通常这是大多数专业字体中的位置(至少从我的有限实验中看来)。这里的截图显示,使用Chaparral(和我拥有的其他一些专业字体),我提供的专用区域Unicode字符确实可以工作。 - Kevin Coppock
@lhunath 看起来那些字体是用于外语的(你会发现该列表中只有一小部分大写小型字符)。大多数字体并不包含所有真正的小型大写字母字符。 - Kevin Coppock
显示剩余4条评论

7

抱歉拿出一个非常老的问题。

我喜欢@kcoppock的方法,但不幸的是我正在使用的字体缺少小型大写字母。 我怀疑很多人会发现自己处于这种情况。

这启发我编写了一个小型实用程序方法,它将采用混合大小写字符串(例如Small Caps)并创建一个格式化的可跨度字符串,看起来像Sᴍᴀʟʟ Cᴀᴘs,但仅使用标准的A-Z字符。

  • 它适用于具有A-Z字符的任何字体-无需特殊要求
  • 它可以轻松地在TextView(或任何其他基于文本的视图)中使用
  • 它不需要任何HTML
  • 它不需要编辑您原始的字符串

我在这里发布了代码:https://gist.github.com/markormesher/3e912622d339af01d24e


0

只需调用此getSmallCaps(text)函数:

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

这个小写字母是怎么样的? - Sofi Software LLC
小型大写字母不仅仅是小的大写字母。 - Robin Davies

0

0
这不是我的代码,但它运行得非常完美。
 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;
}

例子:

SpannableString setStringObj = getSmallCapsStringTwo("Object"); tvObj.setText(setStringObj);

-2

在XML中,编辑文本具有属性:android:capitalize=""


1
但是它会像 OP 想要的那样是小型大写字母吗?我不确定。 - MysticMagicϡ
先在 XML 中尝试一下这个。 - deepak825
@deepak825 无论你在这里提供什么答案,都应该添加到评论中。 - Sankar V
1
@deepak825 我需要类似于小型大写字母的东西。 - naz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接