如何更改Android中Webview的字体?

发布于 2024-09-27 00:24:19 字数 427 浏览 1 评论 0 原文

我想将 webview 的默认字体更改为自定义字体。我正在使用 webview 开发 Android 的双语浏览器应用程序。

我尝试通过将自定义字体放入资产中来获取自定义字体的实例。但仍然无法将 webview 的默认字体设置为我的字体。

这就是我尝试过的:

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

任何人都可以纠正这个问题或建议任何其他方法将 webview 的默认字体更改为自定义字体吗?

谢谢!

I want change the default font of webview to a custom font. I'm using webview in developing an bilingual browser app for Android.

I tried getting an instance of custom typeface by placing my custom font in assets. But still couldn't set webview's default font to my font.

This is what I tried:

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

Can anyone correct this or suggest any other method to change webview's default font to a custom font?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

一桥轻雨一伞开 2024-10-04 00:24:19

此项目中有一个有效的示例。归结为:

  1. 在您的 assets/fonts 文件夹中,放置所需的 OTF 或 TTF 字体(此处为 MyFont.otf)
  2. 创建一个用于 WebView 内容的 HTML 文件,在里面assets 文件夹(位于 assets/demo/my_page.html 内):

    <代码>
    <头>
    <样式类型=“text/css”>
    @font-face {
        字体系列:MyFont;
        src: url("file:///android_asset/fonts/MyFont.otf")
    }
    身体 {
        字体系列:MyFont;
        字体大小:中等;
        文本对齐:对齐;
    }
    
    
    <正文>
    您的文字可以放在这里!您的文字可以放在这里!您的文字可以放在这里!
    
    
    
  3. 从代码中将 HTML 加载到 WebView 中:

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

请注意,不允许通过 loadData() 注入 HTML。 作为根据文档

请注意,JavaScript 的同源策略意味着在使用此方法加载的页面中运行的脚本将无法访问使用“data”以外的任何方案(包括“http(s)”)加载的内容。要避免此限制,请使用带有适当基本 URL 的 loadDataWithBaseURL()。

正如 @JaakL 在下面的评论中建议的那样,要从字符串加载 HTML,您应该提供指向您的资源的基本 URL:

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

当引用 htmlData 中的字体时,您可以简单地使用 /fonts/MyFont.otf(省略基本 URL)。

There's a working example of this in this project. It boils down to:

  1. In your assets/fonts folder, place the desired OTF or TTF font (here MyFont.otf)
  2. Create a HTML file that you'll use for the WebView's content, inside the assets folder (here inside 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. Load the HTML into the WebView from code:

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

Take note that injecting the HTML through loadData() is not permitted. As per the documentation:

Note that JavaScript's same origin policy means that script running in a page loaded using this method will be unable to access content loaded using any scheme other than 'data', including 'http(s)'. To avoid this restriction, use loadDataWithBaseURL() with an appropriate base URL.

As @JaakL suggests in the comment below, for loading HTML from a string, you should instead provide the base URL pointing to your assets:

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

When referencing the font in htmlData, you may then simply use /fonts/MyFont.otf (omitting the base URL).

陌伤浅笑 2024-10-04 00:24:19

我正在使用此代码

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

I am using this code :

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);
影子是时光的心 2024-10-04 00:24:19

更简单的是,您可以使用资产 URL 格式来引用字体。无需编程!

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

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

...

Even simpler, you can use the Asset URL format to reference the font. No programming needed!

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

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

...

踏月而来 2024-10-04 00:24:19

可以在 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");

It can be done in Android. I took three days to solve this issue. But now it seems very easy.
Follow these steps to set custom font for Webview

1.Add your font to assets folder
2.Copy the font to application's files directory

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.You have to call above function only once (you have to find some logic for this).

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

4.Use the below code to set value for your webview. Here I am using CSS to set font.

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.You can call the above function as below

webview.loadDataWithBaseURL(null, getHtmlData(activity,htmlData) , "text/html", "utf-8", "about:blank");
╰ゝ天使的微笑 2024-10-04 00:24:19

我通过上面的答案完成了这个添加:

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

谢谢大家:)

i done this by upper answers with this additions:

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

and then use 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>" : "");
}

thanks to everybody:)

树深时见影 2024-10-04 00:24:19

如果您像我一样将字体放在 res/font 下,那么您可以将目录更改为以下内容:-

@font-face {
     font-family: yourfont;
     src: url("file:///android_res/font/yourfont.ttf")
}
        
body {
     font-family: yourfont;
}

If you are putting fonts under res/font like me, then you can change the dir to the following:-

@font-face {
     font-family: yourfont;
     src: url("file:///android_res/font/yourfont.ttf")
}
        
body {
     font-family: yourfont;
}
昇り龍 2024-10-04 00:24:19

如果您的资产文件夹中包含内容,那么上述许多答案都会发挥作用。

但是,如果您像我一样想要将所有资源从服务器下载并保存到内部存储,您可以使用 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", "");

上面的 html 中使用的 CSS 文件(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) 所以我不知道它是否适用于其他版本

Many of the above answers work lie a charm if you have your content in your assets folder.

However, if you like me want to download and save all your assets from a server to your internal storage you can instead use loadDataWithBaseURL and use a reference to your internal storage as the baseUrl. Then all files there will be relative to the loaded html and are found and used correctly.

In my internal storage I have saved the following files:

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

Then I use the following code:

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

The CSS file used in the above html (style.css):

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

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

I have only tried this while targeting minSdkVersion 19 (4.4) so I have no idea if it works on other versions

蒗幽 2024-10-04 00:24:19
 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);
 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);
╭⌒浅淡时光〆 2024-10-04 00:24:19

响应兼容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)
    }
}

使用 loadDataWithBaseURL 加载 HTML 内容。

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()

Response compatible with Android 11 (API 30) or above.

I saw a lot of answers, but none of them was working on Android 11+. For me, the solution was: WebAssetLoader.

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

In my case, the font is in res/font folder.

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

Load the HTML content using loadDataWithBaseURL.

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

The getStyledHtmlContent returns your HTML content.

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()
冷夜 2024-10-04 00:24:19

您不需要使用本地 ttf 文件来设置 Android 的 webview 字体,它会增加整个应用程序的大小。

您还可以使用在线字体,例如谷歌字体...这将有助于减小您的 apk 大小。

例如:访问以下网址

您将找到使用此字体的必要信息。然后创建一个如下所示的字符串

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

。您将能够通过这种方式从外部源加载字体。

现在应用程序字体怎么样,为网络视图使用一种字体并为整个应用程序使用不同的字体是没有意义的。因此,您可以在应用中使用可下载字体它还使用外部源在应用程序中加载字体。

You need not use local ttf file to set webview font for android, It will increase the whole app size.

you can also use online fonts like google's font... It will help to reduce your apk size.

For example: visit the below URL
https://gist.github.com/karimnaaji/b6c9c9e819204113e9cabf290d580551#file-googlefonts-txt

You will found necessary info to use this font. then create a String like below

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

then load the webview like this

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

done. You will able to load the font from the external source in this way.

Now whats about the app font, it doesn't make sense to use 1 font for the webview and different font for the whole app. So you can use Downloadable Fonts in your app which also uses external sources for loading fonts in the app.

木格 2024-10-04 00:24:19

测试一下,就像魅力一样为我工作:

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

test it, work for me like a charm :

   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);
    }
浅语花开 2024-10-04 00:24:19

您可以使用 CSS 来做到这一点。我用一个应用程序做到了这一点,但它在 Android 2.1 中不起作用,因为 Android 浏览器 2.1 存在一个已知错误。

You can do it by using CSS. I did it with an app but it won't work in Android 2.1 as there is an known bug with Android browser 2.1.

殤城〤 2024-10-04 00:24:19

问题是它需要位于一个文件夹中,请尝试将“./myfont.ttf”放入文件夹中,如果不将字体放入诸如“fonts/myfont.ttf”之类的资产中的文件夹中,那么肯定会起作用。

The issue is it needs to be in a folder, try putting "./myfont.ttf" instead, if not put the font inside a folder in assets like "fonts/myfont.ttf" that will work for sure.

Spring初心 2024-10-04 00:24:19

使用 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");

Use https://github.com/delight-im/Android-AdvancedWebView library.

in html data :

<!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>

in xml :

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

in java :

advancedWebView = findViewById(R.id.advanced_web_view);
advancedWebView.loadHtml(htmlData, "text/html; charset=utf-8", "utf-8");
风情万种。 2024-10-04 00:24:19

这是在 Web 视图中加载 htmlData 的方法:

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

其中 getHtmlData(activity,**htmlData**) 返回一串 html 代码。

This is how do you load htmlData in a webview:

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

where getHtmlData(activity,**htmlData**) returns a string of html code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文