Jak zmienić krój czcionki Webview w systemie Android?

97

Chcę zmienić domyślną czcionkę widoku internetowego na czcionkę niestandardową. Używam Webview do tworzenia dwujęzycznej przeglądarki na Androida.

Próbowałem uzyskać niestandardowy krój, umieszczając moją niestandardową czcionkę w zasobach. Ale nadal nie mogłem ustawić domyślnej czcionki Webview na moją czcionkę.

Oto, czego próbowałem:

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

Czy ktoś może to poprawić lub zasugerować inną metodę zmiany domyślnej czcionki Webview na niestandardową czcionkę?

Dzięki!

Dhanika
źródło
W końcu zdałem sobie sprawę, że nie da się tego zrobić.
Dhanika
cześć, czy znalazłeś jakieś rozwiązanie dla tej rzeczy z czcionką, próbuję dla hindi font stackoverflow.com/q/5868198/501859 . pomóż mi, jeśli masz rozwiązanie
Kishore
@Dhanika, jak rozwiązać ten problem w obliczu tego samego problemu.
NagarjunaReddy
Skorzystaj z

Odpowiedzi:

112

W tym projekcie jest działający przykład . Sprowadza się do:

  1. W swoim assets/fontsfolderze umieść żądaną czcionkę OTF lub TTF (tutaj MyFont.otf)
  2. Utwórz plik HTML, którego będziesz używać dla zawartości WebView, w assetsfolderze (tutaj w środku 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. Załaduj kod HTML do WebView z kodu:

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

Zwróć uwagę, że wstrzykiwanie kodu HTML przez loadData()nie jest dozwolone. Zgodnie z dokumentacją :

Należy pamiętać, że zasada tego samego pochodzenia JavaScript oznacza, że ​​skrypt działający na stronie załadowanej przy użyciu tej metody nie będzie mógł uzyskać dostępu do treści załadowanej przy użyciu innego schematu niż „dane”, w tym „http (s)”. Aby uniknąć tego ograniczenia, użyj funkcji loadDataWithBaseURL () z odpowiednim podstawowym adresem URL.

Jak @JaakL sugeruje w poniższym komentarzu, aby załadować kod HTML z ciągu znaków, należy zamiast tego podać podstawowy adres URL wskazujący na zasoby:

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

Odwołując się do czcionki w htmlData, możesz po prostu użyć /fonts/MyFont.otf(pomijając podstawowy adres URL).

Paul Lammertsma
źródło
10
LoadData () nie działa, ale webView.loadDataWithBaseURL ("file: /// android_asset /", ... działa dobrze. Wtedy też powinno działać odwołanie do pliku czcionki jako "/fonts/MyFont.otf".
JaakL
W moim przypadku dane wracają w postaci tagów z edytora ck (backend api) <div style = \ "text-align: center; \"> <span style = \ "background-color: transparent; \"> < kolor czcionki = \ "# f20505 \" size = \ "5 \" face = \ "Comic Sans MS \"> Podziel się z nami swoją opinią <\ / font> <\ / span> Ustawiam to jako webview.loadData () ale nie bierze czcionek, jakieś rozwiązanie?
B.shruti
Comic Sans MS nie jest czcionką dostarczaną przez Androida. Będzie działać tylko wtedy, gdy zdefiniujesz krój czcionki w CSS i dostarczysz plik czcionki w zasobach aplikacji.
Paul Lammertsma
2
moja czcionka znajduje się w res/fontfolderze. Jaka byłaby wtedy ścieżka? Próbowałem, file:///android_res/font/ale to nie działa.
Wirling
105

Używam tego kodu :

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);
Omid Omidi
źródło
2
O MÓJ BOŻE! To jest dokładnie to, co nas poprowadziło na trop tego, co poszło nie tak: jak się okazuje, Android 4.2 NIE renderuje czcionki, jeśli dodasz „format ('ttf')” za „src: url ('... „)”. Zostaw to, a czcionki będą pięknie renderowane. Przetestowano przy użyciu własnych czcionek internetowych Google.
Pascal Lindelauf
2
To bujające rozwiązanie, Kciuki w górę
Saad Bilal
loadDataWithBaseURL nie działa na Androidzie 4.1 i 4.2 :(
Misha Akopov
nie działa dla mnie w systemie Android 5.1. Skorzystałem z odpowiedzi (Dana Syrstada). różnica polega na notowaniufont-family: 'myface';
Mneckoee
52

Jeszcze prościej, możesz użyć formatu adresu URL zasobu, aby odwołać się do czcionki. Bez programowania!

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

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

...

Dan Syrstad
źródło
1
Jeśli umieszczę plik .ttfi .htmlw tym samym katalogu i załaduję go w przeglądarce Androida, działa. Jednak w WebView mojej aplikacji, podczas gdy CSS pokazuje, tekst pojawia się w domyślnej czcionce Androida pomimo dodania .ttfdo assets/fontsfolderu projektu . Testuję na 2.3.5, ale buduję na 2.1. Czy to może być problem, czy czegoś mi brakuje?
Paul Lammertsma
1
Znalazłem rozwiązanie: jeśli tworzysz plik HTML i umieszczasz go w zasobach, ładujesz go za pośrednictwem view.loadUrl()dzieł, a view.loadData()nie. Nie mam pojęcia, dlaczego ten drugi nie.
Paul Lammertsma
4
Lil 'późno, ale działa z view.loadDataWithBaseUrl (null, content, mime, enconding, null)
Ours
28

Można to zrobić w systemie Android. Rozwiązanie tego problemu zajęło mi trzy dni. Ale teraz wydaje się to bardzo łatwe. Wykonaj poniższe czynności, aby ustawić niestandardową czcionkę dla Webview

1. Dodaj czcionkę do folderu zasobów 2.
Skopiuj czcionkę do katalogu plików aplikacji

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. Powyższą funkcję musisz wywołać tylko raz (musisz znaleźć do tego jakąś logikę).

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

4. Użyj poniższego kodu, aby ustawić wartość widoku internetowego. Tutaj używam CSS, aby ustawić czcionkę.

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. Możesz wywołać powyższą funkcję jak poniżej

webview.loadDataWithBaseURL(null, getHtmlData(activity,htmlData) , "text/html", "utf-8", "about:blank");
dwójkowy
źródło
Cześć! Próbowałem tego podejścia, ale WebView nadal nie ładuje mojej czcionki. Czy zrobiłeś coś specjalnego? Dzięki!
Zarah,
jak to zrobić dla html stackoverflow.com/q/5868198/501859 . pomóż mi, jeśli masz rozwiązanie
Kishore
U mnie to działa. Dzięki Binary.
Ravi Shanker Yadav
Mam ten czcionki w folderze aktywów i zmiany css z tego pełną ścieżkę czcionkę i nazwiska w organizmie, a po modyfikacji znów jestem ładowanie treści, ale może „t natychmiast zobaczyć efekt zmiany czcionki
Ravi
13

zrobiłem to przez górne odpowiedzi z następującymi dodatkami:

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

a następnie użyj 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>" : "");
}


Dziękuję wszystkim:)

Vlad
źródło
Doskonała odpowiedź !!
SANAT
6

Wiele z powyższych odpowiedzi działa, jeśli masz swoje treści w folderze zasobów.

Jeśli jednak chcesz, abym pobierał i zapisywał wszystkie swoje zasoby z serwera do pamięci wewnętrznej, możesz zamiast tego użyć loadDataWithBaseURLi użyć odniesienia do pamięci wewnętrznej jako baseUrl. Wtedy wszystkie pliki będą zależne od załadowanego html i zostaną znalezione i użyte poprawnie.

W mojej pamięci wewnętrznej zapisałem następujące pliki:

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

Następnie używam następującego kodu:

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", "");

Plik CSS użyty w powyższym html (style.css):

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

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

Próbowałem tego tylko podczas kierowania na minSdkVersion 19 (4.4), więc nie mam pojęcia, czy działa na innych wersjach

lejonl
źródło
6
 webview= (WebView) findViewById(R.id.webview);
 String myCustomStyleString="<style type=\"text/css\">@font-face {font-family: MyFont;src: url(\"file:///android_asset/fonts/iranian_sans.ttf\")}body,* {font-family: MyFont; font-size: 13px;text-align: justify;}img{max-width:100%;height:auto; border-radius: 8px;}</style>";
 webview.loadDataWithBaseURL("", myCustomStyleString+"<div style=\"direction:rtl\">"+intentpost.getStringExtra("content")+"</div>", "text/html", "utf-8", null);
Suport Pfrproject
źródło
2
Popraw swoje pytanie, dodając wyjaśnienie, co robisz.
lifeisfoo
2

Nie musisz używać lokalnego pliku ttf, aby ustawić czcionkę widoku internetowego dla Androida, zwiększy to cały rozmiar aplikacji.

możesz także używać czcionek internetowych, takich jak czcionka Google ... Pomoże to zmniejszyć rozmiar pliku APK.

Na przykład: odwiedź poniższy adres URL https://gist.github.com/karimnaaji/b6c9c9e819204113e9cabf290d580551#file-googlefonts-txt

Znajdziesz niezbędne informacje, aby użyć tej czcionki. następnie utwórz ciąg jak poniżej

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;}";

następnie załaduj widok sieciowy w ten sposób

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

Gotowe. W ten sposób będziesz mógł załadować czcionkę z zewnętrznego źródła.

A co z czcionką aplikacji, nie ma sensu używać jednej czcionki dla widoku internetowego i innej czcionki dla całej aplikacji. Możesz więc używać czcionek do pobrania w swojej aplikacji, która również korzysta z zewnętrznych źródeł do ładowania czcionek w aplikacji.

Afjalur Rahman Rana
źródło
1

Możesz to zrobić za pomocą CSS. Zrobiłem to z aplikacją, ale nie będzie działać w systemie Android 2.1, ponieważ jest znany błąd w przeglądarce Androida 2.1.

Mayu Mayooresan
źródło
1

Problem polega na tym, że musi znajdować się w folderze, spróbuj zamiast tego wstawić „./myfont.ttf”, jeśli nie, umieść czcionkę w folderze w zasobach takich jak „fonts / myfont.ttf”, które na pewno zadziałają.

Nathan Schwermann
źródło
0

przetestuj to, pracuj dla mnie jak urok:

   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);
    }
sana ebadi
źródło
0

Jeśli umieszczasz czcionki pod res/fonttakimi jak ja, możesz zmienić katalog na następujący: -

@font-face {
     font-family: yourfont;
     src: url("file:///android_res/font/yourfont.ttf")
}
        
body {
     font-family: yourfont;
}
Ibrahim Ali
źródło
0

Użyj biblioteki https://github.com/delight-im/Android-AdvancedWebView .

w danych 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>

w xml:

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

w java:

advancedWebView = findViewById(R.id.advanced_web_view);
advancedWebView.loadHtml(htmlData, "text/html; charset=utf-8", "utf-8");
Pobierz Arman
źródło
-3

Oto jak ładujesz htmlData w widoku internetowym:

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

gdzie getHtmlData(activity,**htmlData**)zwraca ciąg kodu html.

Alex Aung
źródło