WebView 使用

禁止 webview 处理长按事件

设置 OnLongClickListener 把长按事件消费掉。

web.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        return true;
    }
});

改变字体大小

字体大小的枚举。

    public static enum TextSize {
        SMALLEST(50),
        SMALLER(75),
        NORMAL(100),
        LARGER(125),
        LARGEST(150);

        int value;

        private TextSize(int var3) {
            this.value = var3;
        }
    }

获取 WebSettings,然后设置字体大小。

WebSettings st = wv.getSettings();
st.setTextSize(WebSettings.TextSize.LARGER);

显示 html 文本

示例:示例中用到的 html 文本与 TextView 显示 Html 相同。

private static final String T1 = "<p>Tell me the <font color=\"red\">color</font></p>";
private static final String H1 = "<p>Tell me the <text style=\"color: blue; font-weight: bold;\">color</text>.</p>";
private static final String H1_FIX = "<p>Tell me the <b><font color=\"blue\">color</font></b>.</p>";
​
 wb1.loadData(T1, "text/html", "UTF-8");
 wb2.loadData(H1, "text/html", "UTF-8");
 wb3.loadData(H1_FIX, "text/html", "UTF-8");

layout 中放置 WebView

<WebView
 android:id="@+id/web3"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />

WebView 显示 Html 文本效果图

之前 TextView 显示不出颜色和加粗的 H1,在 webView 中可以正常显示。

上面的 loadData 方法中指定了 mimeType 为 text/html,编码类型 UTF-8

WebView loadData 中文乱码

使用 loadData 出现中文乱码。

String htmlData = "<p>This is me. 我是文本Text.</p>";
webView.loadData(htmlData, "text/html", "UTF-8"); // 某些机型出现中文乱码

使用 loadDataWithBaseURL 方法规避中文乱码问题。

webView.loadDataWithBaseURL(null, htmlData, "text/html", "UTF-8", null);

WebView 加载 assets 中的网页

我们把网页文件放到assets目录中。

设置WebSettings,允许读取文件等等。

assets目录的路径以file:///android_asset/开头。

WebView webView = findViewById(R.id.web2);

String url = "file:///android_asset/drag-to/index.html";
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowContentAccess(true);
webSettings.setDomStorageEnabled(true);
webView.loadUrl(url);

WebView 常见问题

1. 针对加载 webView 中的资源时加快加载的速度优化(主要是针对图片)

原因: html 代码下载到 WebView 后,webkit 开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件,但如果在这之前也有解析到 image 节点,那势必也会发起网络请求下载相应的图片。在网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到 css 或 js 文件加载完成的时间,造成页面空白 loading 过久。

解决方法: 告诉 WebView 先不要自动加载图片,等页面 finish 后再发起图片加载。

//初始化的时候设置,具体代码在WebView类中
if(Build.VERSION.SDK_INT >= KITKAT) {
    //设置网页在加载的时候暂时不加载图片
    webView.getSettings().setLoadsImagesAutomatically(true);} else {
    webView.getSettings().setLoadsImagesAutomatically(false);}

/**
 * 当页面加载完成会调用该方法
 * @param view  view
 * @param url  url链接
 */
@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    //页面finish后再发起图片加载
    if(!webView.getSettings().getLoadsImagesAutomatically()) {
        webView.getSettings().setLoadsImagesAutomatically(true);
    }
}

2.WebView硬件加速导致页面渲染闪烁

原因: 4.0 以上的系统我们开启硬件加速后,WebView 渲染页面更加快速,拖动也更加顺滑。但有个副作用就是,当 WebView 视图被整体遮住一块,然后突然恢复时(比如使用 SlideMenu 将 WebView 从侧边滑出来时),这个过渡期会出现白块同时界面闪烁。

解决方法: 是在过渡期前将 WebView 的硬件加速临时关闭,过渡期后再开启。

//关闭硬件加速
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
//开启硬件加速
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {    webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}

3.可以提前显示加载进度条 原因: WebView.loadUrl("url") 不会立马就回调 onPageStarted 或者 onProgressChanged 因为在这一时间段,WebView 有可能在初始化内核,也有可能在与服务器建立连接,这个时间段容易出现白屏,白屏用户体验是很糟糕的。

解决方法: 提前显示进度条虽然不是提升性能 , 但是对用户体验来说也是很重要的一点。

//正确
pb.setVisibility(View.VISIBLE);
mWebView.loadUrl("https://github.com/");//不太好
@Override
public void onPageStarted(WebView webView, String s, Bitmap bitmap) {
    super.onPageStarted(webView, s, bitmap);
    //设定加载开始的操作
    pb.setVisibility(View.VISIBLE);
}

//下面这个是监听进度条进度变化的逻辑
mWebView.getWebChromeClient().setWebListener(interWebListener);
mWebView.getWebViewClient().setWebListener(interWebListener);
private InterWebListener interWebListener = new InterWebListener() {
    @Override
    public void hindProgressBar() {
        pb.setVisibility(View.GONE);
    }

    @Override
    public void showErrorView() {

    }

    @Override
    public void startProgress(int newProgress) {
        pb.setProgress(newProgress);
    }

    @Override
    public void showTitle(String title) {

    }
};

4. WebView密码明文存储漏洞优化

原因: WebView 默认开启密码保存功能 mWebView.setSavePassword(true),如果该功能未关闭,在用户输入密码时,会弹出提示框,询问用户是否保存密码,如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被***的危险。

解决方法: 通过 WebSettings.setSavePassword(false) 关闭密码保存提醒功能。

//设置是否开启密码保存功能,不建议开启,默认已经做了处理,存在***的危险
WebView.setSavePassword(false);

5.自定义加载异常 error 的状态页面,比如下面这些方法中可能会出现 error

原因: 当WebView加载页面出错时(一般为404 NOT FOUND,Android WebView会默认显示一个出错界面。当WebView加载出错时,会在WebViewClient实例中的onReceivedError()``,还有onReceivedTitle`方法接收到错误。

解决方法: 自定义错误页面样式。

/**
 * 请求网络出现error
 * @param view                              view
 * @param errorCode                         错误
 * @param description                       description
 * @param failingUrl                        失败链接
 */
@Override
public void onReceivedError(WebView view, int errorCode, String description, String
        failingUrl) {
    super.onReceivedError(view, errorCode, description, failingUrl);
    if (errorCode == 404) {
        //用javascript隐藏系统定义的404页面信息
        String data = "Page NO FOUND!";
        view.loadUrl("javascript:document.body.innerHTML=\"" + data + "\"");
    } else {
        if (webListener!=null){
            webListener.showErrorView();
        }
    }
}

// 向主机应用程序报告Web资源加载错误。这些错误通常表明无法连接到服务器。
// 值得注意的是,不同的是过时的版本的回调,新的版本将被称为任何资源(iframe,图像等)
// 不仅为主页。因此,建议在回调过程中执行最低要求的工作。
// 6.0 之后
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    super.onReceivedError(view, request, error);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        X5WebUtils.log("服务器异常"+error.getDescription().toString());
    }
    //ToastUtils.showToast("服务器异常6.0之后");
    //当加载错误时,就让它加载本地错误网页文件
    //mWebView.loadUrl("file:///android_asset/errorpage/error.html");
    if (webListener!=null){
        webListener.showErrorView();
    }
}

/**
 * 这个方法主要是监听标题变化操作的
 * @param view  view
 * @param title 标题
 */
@Override
public void onReceivedTitle(WebView view, String title) {
    super.onReceivedTitle(view, title);
    if (title.contains("404") || title.contains("网页无法打开")){
        if (webListener!=null){
            webListener.showErrorView();
        }
    } else {
        // 设置title
    }
}

Android 零基础入门教程视频参考