如何检测设备支持哪些语言字体?

5

比如说,我想展示一个由10种语言组成的列表,这些语言都是用本地文字书写的。如果手机不支持这些字体,那么就会回退到英文文字。有没有办法检测出特定设备支持哪些字体呢? 换句话说,我只是想检查一下,比如说“旁遮普语”是否能够以“ਪੰਜਾਬੀ”的形式显示。


我有点困惑你的问题是什么:你是想找出设备上安装了哪些字体吗?还是想知道你的语言是否会在设备上显示(使用任何字体)?这些问题有关联但并不完全相同。 - Matter Cat
@MatterCat 我并不关心任何特定的字体族,我只是想检查一下比如“punjabi”是否可以显示为“ਪੰਜਾਬੀ”。 - Ankit
2个回答

3
为了保险起见,我建议同时使用英文和本地语言名称(这也是我实际采取的措施)。请对那些只有本地文字脚本的人多加同情,他们看到所有这些 فارسی 贛語 ગુજરાતી Հայերեն हिन्दी বিষ্ণুপ্রিয়া মণিপুরী עברית ಕನ್ನಡ ქართული ລາວ مصرى नेपाल भाषा Олык марий ភាសាខ្មែរ Српски தமிழ் 文言 ייִדיש 中文 的本地脚本。

您还可以尝试将文本绘制成位图,并检查生成的位图是否为空白。 例如:http://www.skoumal.net/en/android-how-draw-text-bitmapHow to check if a Bitmap is empty (blank) on Android (当然,假设不支持的字母不会显示为黑色钻石或类似物)。

class Util {
    private static final int WIDTH_PX = 200;
    private static final int HEIGHT_PX = 80;

    public static boolean isSupported(Context context, String text) {
        int w = WIDTH_PX, h = HEIGHT_PX;
        Resources resources = context.getResources();
        float scale = resources.getDisplayMetrics().density;
        Bitmap.Config conf = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
        Bitmap orig = bitmap.copy(conf, false);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.rgb(0, 0, 0));
        paint.setTextSize((int) (14 * scale));

        // draw text to the Canvas center
        Rect bounds = new Rect();
        paint.getTextBounds(text, 0, text.length(), bounds);
        int x = (bitmap.getWidth() - bounds.width()) / 2;
        int y = (bitmap.getHeight() + bounds.height()) / 2;

        canvas.drawText(text, x, y, paint);
        boolean res = !orig.sameAs(bitmap);
        orig.recycle();
        bitmap.recycle();
        return res;
    }
}

测试代码:

    String s;
    s="";Log.d("~~~","=="+s+"=="+Util.isSupported(this, s));
    s="中文";Log.d("~~~","=="+s+"=="+Util.isSupported(this, s));
    s="ਪੰਜਾਬੀ";Log.d("~~~","=="+s+"=="+Util.isSupported(this, s));
    s="Հայերեն";Log.d("~~~","=="+s+"=="+Util.isSupported(this, s));

输出:

 ====false
 ==中文==true
 ==ਪੰਜਾਬੀ==false
 ==Հայերեն==true

如果您希望在同一字符串中显示英文和本地名称,可以先检查本地名称是否应在合成两个名称的字符串之前显示,或删除拉丁字符:

public static String stripLatin(String s) {
    String res = "";
    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) > 127) {
            res += s.charAt(i);
        }
    }
    return res;
}

测试代码:

s="Punjabi(ਪੰਜਾਬੀ)";Log.d("~~~","=="+s+"=="+Util.isSupported(this, Util.stripLatin(s)));

这是我将显示“Punjabi(ਪੰਜਾਬੀ)”的方式,所以如果字体没有正确绘制,它将显示带有空格或黑色矩形括号。我想避免的是第二种情况。 - Ankit
public static String stripLatin(String s) { String res = ""; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) > 127) { res += s.charAt(i); } } return res; }Util.isSupported(this, Util.stripLatin(s)) - 18446744073709551615
我在我的设备中没有古吉拉特语,但是_Util.isSupported(this, s)_返回true,这是错误的。 - user6043117
@PiyushGupta 实际上该代码检查字符串中是否至少有一个字符显示为非空白。在 Android 4.04 时代,所有不受支持的字符都将显示为空格。您使用的是哪个版本的 Android?您将哪个字符串传递给了该代码?您的 Android 如何在屏幕上显示该字符串? - 18446744073709551615
我将“ગુજરાતી”作为字符串传递,并在棒棒糖设备上进行测试,它不会显示为空格或方块。它显示的与“ગુજરાતી”相同。 - user6043117
那它支持那种语言,不是吗?嗯,能够显示该语言的文本和在该语言中本地化所有消息的能力是两个不同级别的支持。 - 18446744073709551615

1
根据this,没有直接的方法来实现你想要的功能。那个答案提出了一种比较绘制字形的方法,但是没有程序化、简单的方法来做到这一点。
另一种方法是查看预安装字体支持哪些语言。从Froyo开始,Android上的标准字体是Roboto和Noto——Roboto用于“类似英语”的语言字符,而Noto用于其他所有字符。您可以在here找到完整的Roboto支持字符列表。然后还有专门设计的Noto,旨在防止当字符无法显示时出现奇怪的块状“豆腐”字符。您可以在here找到支持的Noto语言列表。据说每种语言都至少具有基本的Noto字体支持,并能够在自定义安装时支持更复杂的字体(衬线等)。This是一个有用的指南,可以看到每种语言类型可以支持哪种字体。
根据this,除了类似于英语的Roboto字体外,默认系统上安装的主要Noto字体是NotoSerif-Regular。您可以通过查看自己的system_fonts.xml来确认这一点。另一个支持多种语言的字体称为Droid Sans此处列出了它支持的语言列表。

尝试了一些方法,但仍然对我无效。比如旁遮普语和古吉拉特语。显示的是空格,但实际上并不为空(trim()并没有真正去除空格)。 - Ankit
换句话说,它显示了一种语言中的一些字符,但并非全部字符?请检查我发布的Noto链接。你的语言是否在其中列出? - Matter Cat

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