【问题标题】:Android assets retrieve embedded font for TypefaceAndroid 资产检索 Typeface 的嵌入字体
【发布时间】:2015-02-21 09:34:44
【问题描述】:

我已经设法嵌入了一种可以通过 Typeface.createFromAsset 访问的字体,但是,还有“file:///android_asset/..”协议。

我尝试对 Typeface.createFromFile 使用“file:///android_asset/fonts/myfont.ttf”,但这不起作用?奇怪,因为我认为 file:///android_asset 是由系统处理的,因此 Typeface 能够获得 InputStream ?

所以我的具体问题是:为什么 file:///android_asset/ 协议不能与 Typeface.createFromFile 一起使用?

【问题讨论】:

标签: android file assets typeface


【解决方案1】:

对于Typeface.createFromFile(path) 方法,您必须传递与您正在运行应用程序的设备相关的路径。所以这个方法会在设备目录而不是资产文件夹中查找字体文件。如果您提供file:///android_asset/ protocol 之类的路径,则它将找不到设备文件系统。所以它不会起作用。

【讨论】:

  • 好的。不过,您可以将文件创建为文件(URI uri),所以我仍然怀疑我可以将它用于我自己的 URLSchemeHandler 实现吗?我的最终目标是能够从二进制资源创建字体。
  • 二进制资源是什么意思??
  • 我有一个 TrueType 字体,我将它加载到一个字节数组中,即 byte[],并希望从该字节数组创建字体,所以想法是创建一个特殊的 URI 协议和一个 URLSchemeHandler这样我就可以返回一个引用该字节数组的 InputStream。
【解决方案2】:

我选择的解决方案是将二进制数组写入缓存文件,然后将Typeface.createFromFile(path) 与缓存文件一起使用。

解决方案如下:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

public static String bytesToHex (byte[] bytes)
{
    char[] hexChars = new char[bytes.length * 2];

    for (int j = 0; j < bytes.length; ++j)
    {
        int v = bytes[j] & 0xff;
        hexChars[j * 2]     = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0f];
    }

    return new String (hexChars);
}

final private java.util.Map dataCache = new java.util.HashMap();

synchronized private final File getDataCacheFile (byte[] data)
{
    try
    {
        java.security.MessageDigest digest = java.security.MessageDigest.getInstance ("MD5");
        digest.update (data);

        String key = bytesToHex (digest.digest());

        if (dataCache.containsKey (key))
            return (File) dataCache.get (key);

        File f = new File (this.getCacheDir(), "bindata_" + key);
        f.delete();
        FileOutputStream os = new FileOutputStream (f);
        os.write (data, 0, data.length);
        dataCache.put (key, f);
        return f;
    }
    catch (Throwable e) {}

    return null;
}

private final void clearDataCache()
{
    java.util.Iterator it = dataCache.values().iterator();

    while (it.hasNext())
    {
        File f = (File) it.next();
        f.delete();
    }
}

public final Typeface getTypeFaceFromByteArray (byte[] data)
{
    try
    {
        File f = getDataCacheFile (data);

        if (f != null)
            return Typeface.createFromFile (f);
    }
    catch (Exception e)
    {
        Log.e ("<tag>", e.toString());
    }

    return null;
}

【讨论】:

  • 你真的让它工作了吗,在哪个版本的 Android 上? AFAIK,此方法只能用于从system/fonts/ 加载字体,不适用于任何非系统字体。
  • getTypeFaceFromByteArray 可以使用字体作为二进制数据调用,在 4.4.2 上运行良好:) 无论如何。请参阅编辑后的答案。
  • 基本上,您的解决方案意味着Typeface.createFromFile() 可以处理缓存目录中的文件,但至少在我的设备(Android 6.0)上它不能。并据此:androidxref.com/6.0.1_r10/xref/frameworks/base/tools/layoutlib/…(寻找 addFont() 方法) - 它不应该工作。虽然不确定 4.4.2...
  • 感谢您的提醒。我有一段时间没有对此进行测试,所以它可能确实被破坏了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多