我有一个显示框字符的自定义字体。我使用的字体显然不支持所有语言。我想检查我要显示的字符串是否可以通过我的自定义字体显示。如果它不能,那么我想使用标准的Android字体(我知道可以显示字符)。我找不到一种方法来检查我的Typeface是否可以显示特定的字符串。我相信我已经看到了一种方法可以解决这个问题。有人知道吗?
答案 0 :(得分:7)
<强>更新强> 如果您要编写API级别23或更高级别,请使用Paint.hasGlyph()中提到的answer by Orson Baines。否则请参阅下面的原始答案。
正如您在自己的回答中所提到的,没有可用于检查此内容的内置方法。但是,如果您可以控制要检查的字符串/字符,实际上可以通过稍微创新的方法来实现此目的。
您可以在要检查的字体中绘制一个您知道缺少的字符,然后绘制一个您想知道的字符(如果存在),然后最终比较它们并查看它们是否相同。
以下是一个代码示例,说明了我如何实施此检查:
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);
}
使用此方法时要记住一些重要的限制:
isCharacterMissing
的参数)必须是非空格(可以使用Character.isWhitespace()检测到)。在某些字体中,缺少的字符会呈现为空格,因此如果您要比较存在的空白字符,则会错误地将其报告为这些字体中的缺失字符。missingCharacter
成员必须是要检查的字体中已知缺少的字符。我正在使用的代码点U+0978是Devanagari Unicode块中间的保留代码点,因此当前在所有Unicode兼容字体中都应该丢失它,但将来当新的字符添加到Unicode时此代码点可能被分配给真实角色。因此,这种方法不是未来的证明,但如果您自己提供字体,则可以确保在更改应用程序的字体时使用缺少的字符。<强>更新强>
看待U + 0978的解决方案没有其他人指出的那么长。该字符已添加到Unicode 7.0的June 2014版本中。另一种选择是使用unicode中存在的字形,但不太可能以普通字体使用。
U+124AB块中的Early Dynastic Cuneiform可能根本不存在于许多字体中。
答案 1 :(得分:6)
从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);
答案 2 :(得分:2)
@nibarius答案效果很好,但有不同的角色:&#34; \ u2936&#34;。
然而,该解决方案在内存,CPU和时间上都很重要。 我需要一个极少数字符的解决方案,所以我实现了 a&#34;快速而肮脏&#34;通过仅检查边界来解决问题。它的工作速度提高了约50倍,因此更适合我的情况:
public boolean isCharGlyphAvailable(char... c) {
Rect missingCharBounds = new Rect();
char missingCharacter = '\u2936';
paint.getTextBounds(c, 0, 1, missingCharBounds); // takes array as argument, but I need only one char.
Rect testCharsBounds = new Rect();
paint.getTextBounds(c, 0, 1, testCharsBounds);
return !testCharsBounds.equals(missingCharBounds);
}
我应该警告这种方法不如@nibarius准确,并且有一些误报和误报,但是如果你只需要测试几个字符以便能够回退到其他字符 - 这个解决方案是大。
答案 3 :(得分:2)
请检查Googles Mozc项目的源代码。 EmojiRenderableChecker类看起来效果很好!
它就像Paint.hasGlypgh的compat版本(在Marshmallow中添加)。
答案 4 :(得分:2)
对于那些仍然希望你的应用程序与少于23的API兼容并仍在代码中使用hasGlyph函数的人,可以通过以下方式使用@TargetApi(23):
@TargetApi(23)
public boolean isPrintable( String c ) {
Paint paint=new Paint();
boolean hasGlyph=true;
hasGlyph=paint.hasGlyph(c);
return hasGlyph;
}
然后在你的代码中:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(isPrintable(yourString)) {
//Do Something
}
}
唯一的问题是,在低于23的API中,您的应用可能会显示空白符号。但至少在API23 +中你的应用程序将是完美的。
答案 5 :(得分:1)
要检查音乐符号♫是否以字符串形式显示(如果某些设备上没有显示),您可以尝试measuring字符串宽度; if width == 0
然后符号不存在。
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect rtt = new Rect();
paint.getTextBounds( "♫", 0, 1, rtt );
if( rtt.width() == 0 ){
}