检查自定义字体是否可以显示字符

tim*_*yjc 11 android custom-font typeface

我有一个显示框字符的自定义字体.我使用的字体显然不支持所有语言.我想检查我要显示的字符串是否可以通过我的自定义字体显示.如果它不能,那么我想使用标准的Android字体(我知道可以显示字符).我找不到一种方法来检查我的Typeface是否可以显示特定的字符串.我相信我已经看到了一种方法可以解决这个问题.谁知道?

nib*_*ius 7

更新: 如果您正在编写API级别23或更高级别,请使用Orson Baines答案中提到的Paint.hasGlyph().否则请看下面的原始答案.


正如您在自己的回答中提到的,没有内置方法可用于检查.但是,如果您可以控制要检查的字符串/字符,实际上可以通过稍微创新的方法来实现.

您可以在要检查的字体中绘制一个您知道缺少的字符,然后绘制一个您想知道的字符(如果存在),然后最终比较它们并查看它们是否相同.

这是一个代码示例,说明了我如何实现此检查:

public Bitmap drawBitmap(String text){
    Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ALPHA_8);
    Canvas c = new Canvas(b);
    c.drawText(text, 0, BITMAP_HEIGHT / 2, paint);
    return b;
}

public byte[] getPixels(Bitmap b) {
    ByteBuffer buffer = ByteBuffer.allocate(b.getByteCount());
    b.copyPixelsToBuffer(buffer);
    return buffer.array();
}
public boolean isCharacterMissingInFont(String ch) {
    String missingCharacter = "\u0978"; // reserved code point in the devanagari block (should not exist).
    byte[] b1 = getPixels(drawBitmap(ch));
    byte[] b2 = getPixels(drawBitmap(missingCharacter));
    return Arrays.equals(b1, b2);
}
Run Code Online (Sandbox Code Playgroud)

使用此方法时要记住一些重要的限制:

  • 您检查的字符(参数isCharacterMissing)必须是非空格(可以使用Character.isWhitespace()检测).在某些字体中,缺少的字符会呈现为空格,因此如果要比较存在的空白字符,则会错误地将其报告为这些字体中的缺失字符.
  • missingCharacter成员必须是要检查的字体中已知缺少的字符.我正在使用的代码点U + 0978是Devanagari Unicode块中间的保留代码点,因此当前在所有Unicode兼容字体中都应该丢失它,但是将来当将新字符添加到Unicode时,此代码点可能会被分配给一个真正的角色.因此,这种方法不是未来的证明,但如果您自己提供字体,则可以确保在更改应用程序的字体时使用缺少的字符.
  • 由于这个检查是通过绘制位图并比较它们来完成的,因此它不是非常有效,所以它只应用于检查应用程序中的几个字符而不是所有字符串.

更新:

如其他人所指出的那样,看待U + 0978的解决方案并不奏效.该角色于20146月Unicode 7.0版本中添加.另一种选择是使用存在于unicode中的字形,但不太可能在普通字体中使用.

早期楔形块中的U + 124AB可能是许多字体中根本不存在的东西.

  • 股票Nexus 4有一个"\ u0978"的字形.相反,"\ u2936"似乎仍然缺失. (2认同)

Ors*_*nes 7

从Android版本23开始,您可以像这样测试它:

Typeface typeface;
//initialize the custom font here

//enter the character to test
String charToTest="\u0978";
Paint paint=new Paint();
paint.setTypeface(typeface);
boolean hasGlyph=paint.hasGlyph(charToTest);
Run Code Online (Sandbox Code Playgroud)

  • 来自JavaDoc:"检查是在整个回退链上完成的,而不仅仅是引用的直接字体." 因此,如果您只想知道它是否在您指定的字体中,则无效. (2认同)