Как изменить начертание шрифта Webview в Android?

Я хочу изменить шрифт по умолчанию для веб-просмотра на собственный шрифт. Я использую webview при разработке двуязычного браузерного приложения для Android.

Я попытался получить экземпляр пользовательского шрифта, разместив свой собственный шрифт в активах. Но все еще не мог установить шрифт по умолчанию для моего шрифта.

Вот что я пробовал:

Typeface font = Typeface.createFromAsset(getAssets(), "myfont.ttf"); 
private WebView webview;
WebSettings webSettings = webView.getSettings();
webSettings.setFixedFontFamily(font);

Может ли кто-нибудь исправить это или предложить какой-либо другой метод изменения шрифта по умолчанию для веб-просмотра на собственный шрифт?

Спасибо!


person Dhanika    schedule 10.10.2010    source источник
comment
Наконец я понял, что это невозможно.   -  person Dhanika    schedule 09.12.2010
comment
Проверь это. stackoverflow.com / questions / 1344080 /   -  person Samuel    schedule 18.04.2011
comment
привет, ты нашел какое-либо решение для этой вещи со шрифтом, я пытаюсь использовать шрифт хинди stackoverflow.com/q/5868198/501859. помогите мне, если у вас есть решение   -  person Kishore    schedule 27.05.2011
comment
@Dhanika, как решить эту проблему, столкнувшись с той же проблемой.   -  person NagarjunaReddy    schedule 23.03.2013
comment
Пожалуйста, обратитесь по этой ссылке, чтобы установить собственный шрифт в тексте веб-просмотра. stackoverflow.com/a/25692052/3921740 [1] [1]: stackoverflow.com/a/25692052/3921740   -  person user3921740    schedule 05.09.2014


Ответы (15)


Рабочий пример этого есть в этом проекте. Это сводится к:

  1. В папке assets/fonts поместите нужный шрифт OTF или TTF (здесь MyFont.otf)
  2. Создайте HTML-файл, который вы будете использовать для содержимого WebView, внутри папки assets (здесь внутри assets/demo/my_page.html):

    <html>
    <head>
    <style type="text/css">
    @font-face {
        font-family: MyFont;
        src: url("file:///android_asset/fonts/MyFont.otf")
    }
    body {
        font-family: MyFont;
        font-size: medium;
        text-align: justify;
    }
    </style>
    </head>
    <body>
    Your text can go here! Your text can go here! Your text can go here!
    </body>
    </html>
    
  3. Загрузите HTML-код в WebView из кода:

    webview.loadUrl("file:///android_asset/demo/my_page.html");
    

Обратите внимание, что вставка HTML через loadData() не разрешена. Как согласно документации:

Обратите внимание, что та же политика происхождения JavaScript означает, что сценарий, запущенный на странице, загруженной с помощью этого метода, не сможет получить доступ к содержимому, загруженному с использованием любой схемы, кроме «данных», включая «http (s)». Чтобы избежать этого ограничения, используйте loadDataWithBaseURL () с соответствующим базовым URL.

Как предлагает @JaakL в комментарии ниже, для загрузки HTML из строки вы должны вместо этого предоставить базовый URL-адрес, указывающий на ваши ресурсы:

webView.loadDataWithBaseURL("file:///android_asset/", htmlData);

При ссылке на шрифт в htmlData вы можете просто использовать /fonts/MyFont.otf (опуская базовый URL).

person Paul Lammertsma    schedule 12.09.2011
comment
LoadData () не работает, но webView.loadDataWithBaseURL (file: /// android_asset /, ... работает нормально. Тогда также должна работать ссылка на файл шрифта как /fonts/MyFont.otf. - person JaakL; 01.12.2011
comment
В моем случае данные возвращаются в виде тегов из редактора ck (backend api) ‹div style = \ text-align: center; \› ‹span style = \ background-color: transparent; \› ‹font color = \ # f20505 \ size = \ 5 \ face = \ Comic Sans MS \ ›Поделитесь с нами своим мнением‹ \ / font ›‹ \ / span ›Я устанавливаю его как webview.loadData (), но он не использует шрифты, любое решение ?? - person B.shruti; 23.08.2019
comment
Comic Sans MS не является шрифтом Android. Это будет работать только в том случае, если вы определили начертание шрифта в CSS и предоставили файл шрифта в активах вашего приложения. - person Paul Lammertsma; 29.08.2019
comment
мой шрифт находится в папке res/font. Какой тогда будет путь? Я пробовал file:///android_res/font/, но похоже, что это не работает. - person Wirling; 25.10.2019

Я использую этот код:

wv = (WebView) findViewById(R.id.webView1);
String pish = "<html><head><style type=\"text/css\">@font-face {font-family: MyFont;src: url(\"file:///android_asset/font/BMitra.ttf\")}body {font-family: MyFont;font-size: medium;text-align: justify;}</style></head><body>";
String pas = "</body></html>";
String myHtmlString = pish + YourTxext + pas;
wv.loadDataWithBaseURL(null,myHtmlString, "text/html", "UTF-8", null);
person Omid Omidi    schedule 20.02.2014
comment
МОЙ БОГ! ЭТО именно то, что поставило нас на след того, что пошло не так: как оказалось, Android 4.2 НЕ отображает шрифт, если вы добавляете формат ('ttf') за предложением src: url ('...') . Оставьте это, и шрифты будут отображаться красиво. Протестировано с использованием собственных веб-шрифтов Google. - person Pascal Lindelauf; 20.06.2014
comment
Это потрясающее решение, пальцы вверх - person Saad Bilal; 26.03.2015
comment
loadDataWithBaseURL не работает на версиях android 4.1 и 4.2 :( - person Misha Akopov; 11.02.2016
comment
у меня не работало в android 5.1. Я использовал ответ (Дэна Сирстада). разница в цитате font-family: 'myface'; - person Mneckoee; 15.11.2016

Еще проще, вы можете использовать формат URL-адреса ресурса для ссылки на шрифт. Никакого программирования не требуется!

@font-face {
   font-family: 'myface';
   src: url('file:///android_asset/fonts/myfont.ttf'); 
} 

body { 
   font-family: 'myface', serif;

...

person Dan Syrstad    schedule 20.04.2011
comment
Если я помещаю файлы .ttf и .html в один и тот же каталог и загружаю их в браузер Android, он работает. Однако в моем приложении WebView, пока отображается CSS, текст отображается шрифтом Android по умолчанию, несмотря на добавление .ttf в папку проекта assets/fonts. Я тестирую 2.3.5, но строю против 2.1. Может быть, это проблема или что-то мне не хватает? - person Paul Lammertsma; 13.09.2011
comment
Я нашел решение: если вы создадите файл HTML и поместите его в активы, загрузка его через view.loadUrl() работает, а view.loadData() - нет. Я понятия не имею, почему последний не делает. - person Paul Lammertsma; 13.09.2011
comment
Немного поздно, но он работает с view.loadDataWithBaseUrl (null, content, mime, enconding, null) - person Ours; 09.04.2013

Это можно сделать в Android. На решение этой проблемы у меня ушло три дня. Но теперь это кажется очень простым. Выполните следующие действия, чтобы установить собственный шрифт для Webview.

1. Добавьте шрифт в папку с ресурсами
2. Скопируйте шрифт в папку с файлами приложения.

private boolean copyFile(Context context,String fileName) {
        boolean status = false;
        try { 
            FileOutputStream out = context.openFileOutput(fileName, Context.MODE_PRIVATE);
            InputStream in = context.getAssets().open(fileName);
            // Transfer bytes from the input file to the output file
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            // Close the streams
            out.close();
            in.close();
            status = true;
        } catch (Exception e) {
            System.out.println("Exception in copyFile:: "+e.getMessage());
            status = false;
        }
        System.out.println("copyFile Status:: "+status);
        return status;
    }

3. Вы должны вызвать вышеуказанную функцию только один раз (для этого нужно найти логику).

copyFile(getContext(), "myfont.ttf");

4. С помощью приведенного ниже кода установите значение для вашего веб-просмотра. Здесь я использую CSS для установки шрифта.

private String getHtmlData(Context context, String data){
    String head = "<head><style>@font-face {font-family: 'verdana';src: url('file://"+ context.getFilesDir().getAbsolutePath()+ "/verdana.ttf');}body {font-family: 'verdana';}</style></head>";
    String htmlData= "<html>"+head+"<body>"+data+"</body></html>" ;
    return htmlData;
 }

5. Вы можете вызвать вышеуказанную функцию, как показано ниже.

webview.loadDataWithBaseURL(null, getHtmlData(activity,htmlData) , "text/html", "utf-8", "about:blank");
person binary    schedule 24.03.2011
comment
Привет! Я пробовал этот подход, но WebView по-прежнему не загружает мой шрифт. Вы сделали что-нибудь особенное? Спасибо! - person Zarah; 25.05.2011
comment
как это сделать для html stackoverflow.com/q/5868198/501859. помогите мне, если у вас есть решение - person Kishore; 27.05.2011
comment
У меня работает.Спасибо двоичному. - person Ravi Shanker Yadav; 23.12.2013
comment
У меня есть шрифт в папке с ресурсами и я меняю css с этим полным путем к шрифту и имени семейства шрифтов в теле, и после модификации я снова загружаю контент, но не могу сразу увидеть эффект изменения шрифта - person Ravi; 10.04.2014

Я сделал это верхними ответами с этими дополнениями:

webView.loadDataWithBaseURL("file:///android_asset/",
                            WebClient.getStyledFont(someText),
                            "text/html; charset=UTF-8", null, "about:blank");

а затем используйте src: url("file:///android_asset/fonts/YourFont...

public static String getStyledFont(String html) {
    boolean addBodyStart = !html.toLowerCase().contains("<body>");
    boolean addBodyEnd = !html.toLowerCase().contains("</body");
    return "<style type=\"text/css\">@font-face {font-family: CustomFont;" +
            "src: url(\"file:///android_asset/fonts/Brandon_reg.otf\")}" +
            "body {font-family: CustomFont;font-size: medium;text-align: justify;}</style>" +
            (addBodyStart ? "<body>" : "") + html + (addBodyEnd ? "</body>" : "");
}


всем спасибо :)

person Vlad    schedule 08.06.2016
comment
Идеальный ответ !! - person SANAT; 22.01.2018

Многие из приведенных выше ответов работают очаровательно, если у вас есть контент в папке с ресурсами.

Однако, если вы, как и я, хотите загрузить и сохранить все ваши ресурсы с сервера во внутреннее хранилище, вы можете вместо этого использовать loadDataWithBaseURL и использовать ссылку на свое внутреннее хранилище в качестве baseUrl. Тогда все файлы будут относиться к загруженному html и будут правильно найдены и использованы.

В моем внутреннем хранилище я сохранил следующие файлы:

  • IndigoAntiqua2Text-Regular.ttf
  • style.css
  • image.png

Затем я использую следующий код:

WebView web = (WebView)findViewById(R.id.webby);
//For avoiding a weird error message
web.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

String webContent = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><link rel=\"stylesheet\" href=\"style.css\"></head>"
                            + "<body><img src='image.png' width=\"100px\"><div class=\"running\">I am a text rendered with INDIGO</div></body></html>";

String internalFilePath = "file://" + getFilesDir().getAbsolutePath() + "/";
web.loadDataWithBaseURL(internalFilePath, webContent, "text/html", "UTF-8", "");

Файл CSS, используемый в приведенном выше html (style.css):

@font-face {
  font-family: 'MyCustomRunning';
  src: url('IndigoAntiqua2Text-Regular.ttf')  format('truetype');
}

.running{
    color: #565656;
     font-family: "MyCustomRunning";
     font-size: 48px;
}

Я пробовал это только при таргетинге на minSdkVersion 19 (4.4), поэтому понятия не имею, работает ли он в других версиях.

person lejonl    schedule 24.06.2015

Если вы помещаете шрифты в res/font, как я, вы можете изменить каталог на следующее: -

@font-face {
     font-family: yourfont;
     src: url("file:///android_res/font/yourfont.ttf")
}
        
body {
     font-family: yourfont;
}
person Ibrahim Ali    schedule 17.07.2020
comment
Это позволило мне не использовать один и тот же шрифт 2 раза. Спасибо! - person Tgo1014; 09.01.2021

Вам не нужно использовать локальный ttf-файл для установки шрифта webview для Android, это увеличит размер всего приложения.

вы также можете использовать онлайн-шрифты, такие как шрифт Google ... Это поможет уменьшить размер вашего apk.

Например: посетите следующий URL-адрес https://gist.github.com/karimnaaji/b6c9c9e819204113e9cabf290d580551#file-googlefonts-txt

Вы найдете необходимую информацию для использования этого шрифта. затем создайте строку, как показано ниже

String font = "@font-face {font-family: MyFont;src: url(\"here you will put the url of the font which you get previously\")}body {font-family: MyFont;font-size: medium;text-align: justify;}";

затем загрузите веб-просмотр следующим образом

webview.loadDataWithBaseURL("about:blank", "<style>" +font+</style>" + "your html contnet here", "text/html", null, null);

сделано. Таким образом вы сможете загрузить шрифт из внешнего источника.

Что касается шрифта приложения, нет смысла использовать один шрифт для веб-просмотра и другой шрифт для всего приложения. Таким образом, вы можете использовать загружаемые шрифты в своем app, который также использует внешние источники для загрузки шрифтов в приложение.

person Afjalur Rahman Rana    schedule 27.07.2019

Вы можете сделать это с помощью CSS. Я сделал это с помощью приложения, но оно не будет работать в Android 2.1, так как в браузере Android 2.1 есть известная ошибка.

person Community    schedule 13.02.2011

Проблема в том, что он должен быть в папке, попробуйте вместо этого поместить «./myfont.ttf», если не поместите шрифт в папку в ресурсах, таких как «fonts / myfont.ttf», которые наверняка будут работать.

person Nathan Schwermann    schedule 12.07.2013

протестируйте, работайте для меня как шарм:

   private void setResult() {

        String mimeType = "text/html;charset=UTF-8";
        String encoding = "utf-8";
        String htmlText = htmlPrivacy;

        String text = "<html><head>"
                + "<style type=\"text/css\">@font-face {font-family: MyFont;src: url(\"file:///android_asset/fonts/iy_reg.ttf\")}body{font-family: MyFont;color: #666666}"
                + "</style></head>"
                + "<body>"
                + htmlText
                + "</body></html>";

        webView.loadDataWithBaseURL(null, text, mimeType, encoding, null);
    }
person sana ebadi    schedule 06.11.2019

Используйте библиотеку https://github.com/delight-im/Android-AdvancedWebView.

в данных html:

<!doctype html>
<html>

<head>
<style type="text/css">
@font-face {
    font-family: MyFont;
    src: url("file:///android_asset/fonts/font1.ttf")
}
body {
    font-family: MyFont;
    font-size: medium;
    text-align: justify;
}
</style>
<meta http-equiv="Content-Type" content="text/html;  charset=utf-8">
<title>Title</title>
</head>

<body>

    ------ YOUR_CONTENT ------

</body>

</html>

в xml:

<im.delight.android.webview.AdvancedWebView
    android:id="@+id/advanced_web_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

в java:

advancedWebView = findViewById(R.id.advanced_web_view);
advancedWebView.loadHtml(htmlData, "text/html; charset=utf-8", "utf-8");
person Arman Download    schedule 01.08.2020

Ответ совместим с Android 11 (API 30) или выше.

Я видел много ответов, но ни один из них не работал на Android 11+. Для меня решение было: WebAssetLoader.

val assetLoader = WebViewAssetLoader.Builder()
    .addPathHandler(
        "/res/", 
        WebViewAssetLoader.ResourcesPathHandler(context))
    .build()

В моем случае шрифт находится в папке res/font.

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

Загрузите содержимое HTML с помощью loadDataWithBaseURL.

webView.loadDataWithBaseURL(
    "https://appassets.androidplatform.net",
    getStyledHtmlContent(),
    "text/html",
    "UTF-8",
    null
)

getStyledHtmlContent возвращает ваш HTML-контент.

private fun getStyledHtmlContent() =
    """
    <html>
    <head>
        <style>
            @font-face {
                font-family: 'AnyNameYouWant';
                src: url('https://appassets.androidplatform.net/res/font/yourfont.otf');
            }
            body {
                font-family: AnyNameYouWant;
                line-height: 1.5;
                text-align: justify;
            }
        </style>
    </head>
    <body>Content of your page</body>
    </html>
    """.trimIndent()
person nglauber    schedule 30.06.2021

Вот как вы загружаете htmlData в веб-просмотр:

webview.loadDataWithBaseURL(null, getHtmlData(activity,**htmlData**) , "text/html", "utf-8", "about:blank");

где getHtmlData(activity,**htmlData**) возвращает строку html-кода.

person Alex Aung    schedule 10.07.2013

person    schedule
comment
Пожалуйста, улучшите свой вопрос, добавив объяснение того, что вы делаете. - person lifeisfoo; 03.09.2017