如何为具有可下载字体的WebView设置FontFamily?

Roh*_*mar 5 android font-face android-webview android-downloadable-fonts

我目前将我的应用重构为使用可下载字体,因此我没有任何字体资产文件。我进行了很多搜索,唯一看到的解决方案是在CSS文件中设置FontFamily,并将src指向资产文件夹。对于可下载的字体,这是不可能的。

Mar*_*yan 0

当使用Android可下载字体时,您可以从FontInfo.getUri()方法获取ttf字体文件的URI 。

FontsContractCompat.FontFamilyResult fontFamilyResult = FontsContractCompat.fetchFonts(view.getContext(), null, fontRequest);
Uri fontUri = fontFamilyResult.getFonts()[0].getUri();
Run Code Online (Sandbox Code Playgroud)

您可以使用此 URI 将 ttf 文件缓存在您的应用程序空间中,您可以在 WebView HTML 和其他地方直接引用该文件。

如果您想使用 URI 模型,请注意,您不能直接使用 FontsContractCompat 返回的 URI,因为由于加载的内容和此 URI 的基域不同,这可能会违反 CORS 策略。您可以在 WebView HTML 中使用自定义 URI 模式,并在 WebViewClient 的shouldInterceptRequest方法中拦截该请求,在该方法中您可以从 FontsContractCompat 查询或本地缓存的字体文件返回的 URI 返回一个 InputStream (包装为 WebResourceResponse )。

像这样在 css 中形成 URI(需要将 myappscheme://com.myapp.demo 设置为内容的基本 url)

@font-face {
  font-family: Roboto;
  src: url('myappscheme://com.myapp.demo/fonts/name=Roboto');
}
Run Code Online (Sandbox Code Playgroud)

并在 WebViewClient 中。这只是一个演示代码片段。所以在这里添加一些错误处理

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
    {
        Uri requestUri = request.getUrl();
        if (requestUri.getScheme()
                      .equals("myappscheme") && requestUri.getPath()
                                                          .startsWith("fonts"))
        {
            Context context = view.getContext();
            File fontFile = new File(context.getExternalCacheDir(), requestUri.getQueryParameter("name") + ".ttf");
            if (!fontFile.exists())
            {
                FontRequest fontRequest = new FontRequest(
                    "com.google.android.gms.fonts",
                    "com.google.android.gms",
                    requestUri.getQuery(),
                    R.array.com_google_android_gms_fonts_certs);

                FontsContractCompat.FontFamilyResult fontFamilyResult = FontsContractCompat.fetchFonts(view.getContext(), null, fontRequest);
                if (fontFamilyResult.getStatusCode() == FontsContractCompat.FontFamilyResult.STATUS_OK)
                {
                    InputStream gFont = context.getContentResolver()
                                               .openInputStream(fontFamilyResult.getFonts()[0].getUri());
                    fontFile.createNewFile();
                    ByteStreamsKt.copyTo(gFont, new FileOutputStream(fontFile), 4096);
                }
            }
            return new WebResourceResponse("application/octet-stream", null, new FileInputStream(fontFile));
        }
    }
Run Code Online (Sandbox Code Playgroud)