Android(java/kotlin) 加载本地字体

WebView如何加载本地字体

看过网上好多的文章千篇一律,都是这种答案,用 “file:///android_assets/averta.ttf”.
而这种方式本人试下来,都只适用于字体文件存放在当前 [主module] 的assets文件夹下,而最终还是找到了官方的解决方案,能支持字体文件存在于作为主题色的 [子module] 里assets里的情况。完美。
权威还是得官方。宝藏全路径如下:
https://stackoverflow.com/questions/3900658/how-to-change-font-face-of-webview-in-android
https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader

webview.setWebClientForLoadingLocalFontFamily()
        
val htmlContentResult = WebViewUtils.getHtmlWithFontSet("Averta","/res/font/averta_regular.ttf",yourHtmlText)
        
webview.loadDataWithBaseURL(WebViewUtils.FLAG_FONT_SET, htmlContentResult,
                "text/html", "utf-8", null)
class WebViewUtils{
companion object {
        const val FLAG_FONT_SET = "https://appassets.androidplatform.net"

        /**
         * @param filePath is file path but not absolutely path
         * example: the correct format like /res/font/averta_regular.ttf
         * @notice: using this function after [setWebClientForLoadingLocalFontFamily] called.
         */
        fun getHtmlWithFontSet(fontFamily: String, filePath: String, html: String): String {
            val fontStyle =
                "<style type=\"text/css\">@font-face {font-family: $fontFamily;src: url(\"$FLAG_FONT_SET$filePath\")}body,* {font-family: $fontFamily;}</style>"
            return "$fontStyle$html"
        }
    }

    fun setWebClientForLoadingLocalFontFamily(isResourcePath: Boolean = true) {
        context?.let {
            val assetLoader = if (isResourcePath) {
                WebViewAssetLoader.Builder()
                    .addPathHandler(
                        "/res/",
                        WebViewAssetLoader.ResourcesPathHandler(it))
                    .build()
            } else {
                WebViewAssetLoader.Builder()
                    .addPathHandler(
                        "/assets/",
                        WebViewAssetLoader.AssetsPathHandler(it))
                    .build()
            }

            webViewClient = object : WebViewClient() {
                override fun shouldInterceptRequest(
                    view: WebView,
                    request: WebResourceRequest,
                ): WebResourceResponse? {
                    return assetLoader.shouldInterceptRequest(request.url)
                }
            }
        }
    }
}

加载读取本地字体

package com.patrik.message.utils;

import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.drawable.DrawableCompat;

import java.util.Locale;

public class ResourcesUtils {
    /**
     * @param fontsFileName| exmaple:|
     *                       "font/{family}_{weight}.ttf"
     *                       "font/{family}-{weight}.ttf"
     *                       "font/{Family}_{Weight}.ttf"
     *                       "font/{Family}-{Weight}.ttf"
     * @return Typeface || null
     */
    @Nullable
    public static Typeface getFontTypeface(Context context, String fontsFileName) {
        Typeface localTypeface = null;

        if (fontsFileName == null) {
            throw new NullPointerException("Fonts file cannot found");
        }
        if (!fontsFileName.endsWith(".ttf")) {
            throw new IllegalStateException("Fonts file cannot found==>" + fontsFileName);
        }
        String lowerCaseFontsFileName = fontsFileName.toLowerCase(Locale.ROOT);
        String[] splitFontsFileName = lowerCaseFontsFileName.split("\\.");
        if (splitFontsFileName.length != 2) {
            throw new IllegalStateException("Parameter of 'fontsFileName' format is invalid,error_1==>" + lowerCaseFontsFileName + "\nThe correct fonts file format is \"font/{family}_{weight}.ttf\"");
        }
        String[] splitFontsFileName2 = splitFontsFileName[0].split("/");
        if (splitFontsFileName2.length != 2) {
            throw new IllegalStateException("Parameter of 'fontsFileName' format is invalid,error_2==>" + lowerCaseFontsFileName + "\nThe correct fonts file format is \"font/{family}_{weight}.ttf\"");
        }
        try {
            if (context != null) {
                int resId = context.getResources().getIdentifier(splitFontsFileName2[1], splitFontsFileName2[0], context.getPackageName());
                ConversationLog.INSTANCE.i("ChatThemeFont: font resId=" + resId + "|" + splitFontsFileName[0] + "|" + splitFontsFileName2[0] + "|" + context.getPackageName());
                if (resId > 0) {
                    localTypeface = ResourcesCompat.getFont(context, resId);
                } else {
                    localTypeface = Typeface.createFromAsset(context.getAssets(), lowerCaseFontsFileName);
                }
            } else {
                ConversationLog.INSTANCE.e("ChatThemeFont: context cannot be null.please check.");
            }
        } catch (Exception e) {
            ConversationLog.INSTANCE.e("ChatThemeFont: mapping fonts error,fonts file not found==>" + fontsFileName + "|" + e.getMessage());
        }
        return localTypeface;
    }

    public static int getDrawableId(Context context, String drawableName) {
        if (context != null) {
            return context.getResources().getIdentifier(drawableName, "drawable", context.getPackageName());
        } else {
            ConversationLog.INSTANCE.e("ChatThemeDrawable: context cannot be null.please check.");
        }
        return 0;
    }

    @Nullable
    public static Drawable getDrawable(Context context, String drawableName) {
        int resourceId = getDrawableId(context, drawableName);
        if (resourceId != 0) {
            return ContextCompat.getDrawable(context, resourceId);
        }
        return null;
    }

    @Nullable
    public static Drawable getTargetTintDrawable(Drawable drawable, int color) {
        if (drawable != null) {
            Drawable newDrawable = DrawableCompat.wrap(drawable);
            DrawableCompat.setTint(newDrawable, color);
            return newDrawable;
        }
        return null;
    }
}

应该还有种方式可以通过自动生成R.font.id文件加载,但目前没试过.
-----------------------------End-----------------------------

我也是有底线的,感谢您的耐心阅读,欢迎支持与点赞。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容