Android(java/kotlin) 加載本地字體

WebView如何加載本地字體

看過(guò)網(wǎng)上好多的文章千篇一律绊诲,都是這種答案硫豆,用 “file:///android_assets/averta.ttf”.
而這種方式本人試下來(lái)穗椅,都只適用于字體文件存放在當(dāng)前 [主module] 的assets文件夾下吁恍,而最終還是找到了官方的解決方案胰舆,能支持字體文件存在于作為主題色的 [子module] 里assets里的情況册舞。完美蕴掏。
權(quán)威還是得官方。寶藏全路徑如下:
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;
    }
}

應(yīng)該還有種方式可以通過(guò)自動(dòng)生成R.font.id文件加載调鲸,但目前沒(méi)試過(guò).
-----------------------------End-----------------------------

我也是有底線的盛杰,感謝您的耐心閱讀,歡迎支持與點(diǎn)贊藐石。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末即供,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子于微,更是在濱河造成了極大的恐慌逗嫡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件株依,死亡現(xiàn)場(chǎng)離奇詭異驱证,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)恋腕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門抹锄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事伙单』窀撸” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吻育,是天一觀的道長(zhǎng)念秧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)扫沼,這世上最難降的妖魔是什么出爹? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任庄吼,我火速辦了婚禮缎除,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘总寻。我一直安慰自己器罐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布渐行。 她就那樣靜靜地躺著轰坊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪祟印。 梳的紋絲不亂的頭發(fā)上肴沫,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音蕴忆,去河邊找鬼颤芬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛套鹅,可吹牛的內(nèi)容都是我干的站蝠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼卓鹿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菱魔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吟孙,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤澜倦,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后杰妓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體藻治,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年稚失,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栋艳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡句各,死狀恐怖吸占,靈堂內(nèi)的尸體忽然破棺而出晴叨,到底是詐尸還是另有隱情,我是刑警寧澤矾屯,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布兼蕊,位于F島的核電站,受9級(jí)特大地震影響件蚕,放射性物質(zhì)發(fā)生泄漏孙技。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一排作、第九天 我趴在偏房一處隱蔽的房頂上張望牵啦。 院中可真熱鬧,春花似錦妄痪、人聲如沸哈雏。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)裳瘪。三九已至,卻和暖如春罪针,著一層夾襖步出監(jiān)牢的瞬間彭羹,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工泪酱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留派殷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓西篓,卻偏偏與公主長(zhǎng)得像愈腾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岂津,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容