仅需四步它就属于你!—WebView最详解

2019-09-10 14:17:24 浏览数 (1)

前言

新的一天,新的文章,各位花粉肯定已经准备好学习新的知识了,那么今天依旧为大家带来一个实际项目中也非常实用的控件。现在市面上的 App里几乎都内置了 Web网页,比如说很多电商平台,某东、某宝等等,网页具有更新及时、部署方便等特点,移动端往往会搭配 WebView去加载 H5等页面。那么 WebView究竟是何方神圣呢?AndroidWebview在低版本和高版本采用了不同的 webkit版本内核,4.4后使用了 Chrome内核,而 WebView可以对 url请求、页面加载、渲染、页面交互进行处理。

简介

WebView

代码语言:javascript复制
java.lang.Object
   ↳android.view.View
        ↳android.view.ViewGroup
            ↳android.widget.AbsoluteLayout
                ↳android.webkit.WebView

其继承关系如上图所示,下面是一个简单的代码示例:

代码语言:javascript复制
//WebView类下面的方法,通常使用的就是我们用来加载Url
mWebView.loadUrl("http://www.baidu.com");
//也可以配置请求头参数
Map<String, String> headers = new HashMap<>();
headers.put("token", "1234");
mWebView.loadUrl("http://www.baidu.com", headers);
//同样的也可以加载一段Html代码
mWebView.loadData("这里替换成你的html代码", "text/html; charset=UTF-8", null);

这里还有很多 WebView的用法,在实际项目中会碰到很多场景应用到以下方法,所以各位花粉一定要了解,我们将每个方法都非常清晰的描述了一哈,希望可以给已经在开发的新花粉提供帮助:

WebSettings

通常我们需要给默认的 WebView增加一些设置,比如支持缩放, JS交互等属性,这里就要用到 WebSettings,先初始化设置,再给大家讲解一下方法的作用:

代码语言:javascript复制
//声明WebSettings子类
WebSettings ws = mWebView.getSettings();
//页面中与Javascript交互
webSettings.setJavaScriptEnabled(true);

//设置自适应屏幕,两者合用
//将图片调整到适合webview的大小
ws.setUseWideViewPort(true); 
// 缩放至屏幕的大小
ws.setLoadWithOverviewMode(true);

//设置缩放
//设置缩放,默认为true,是setBuiltInZoomControls的前提
ws.setSupportZoom(true); 
//设置内置的缩放控件。true则可以缩放
ws.setBuiltInZoomControls(true); 

//隐藏缩放控件(类似放大镜的图标)
ws.setDisplayZoomControls(false); 
//关闭webview中缓存
ws.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
//设置可以访问文件
ws.setAllowFileAccess(true); 
//支持通过JS打开新窗口
ws.setJavaScriptCanOpenWindowsAutomatically(true); 
//支持自动加载图片
ws.setLoadsImagesAutomatically(true); 
//设置编码格式
ws.setDefaultTextEncodingName("utf-8");
//设置默认的字体大小,默认16,可取值1到72
ws.setDefaultFontSize(36);
/*
 *API21调用
 *当一个安全的来源(origin)试图从一个不安全的来源加载资源时配置WebView的行为。KITKAT以及之前的
 *版本默认值为MIXED_CONTENT_ALWAYS_ALLOW,LOLLIPOP版本默认值MIXED_CONTENT_NEVER_ALLOW,WebView
 *首选的最安全的操作模式为MIXED_CONTENT_NEVER_ALLOW ,不鼓励使用MIXED_CONTENT_ALWAYS_ALLOW。
 */  
ws.setMixedContentMode (WebSettings.MIXED_CONTENT_ALWAYS_ALLOW)
/**
 * LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
 * LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
 * LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
 * LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
*/
ws.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//设置应用缓存文件的路径,为了让应用缓存API可用,此方法必须传入一个应用可写的路径。该方法只会执行一次
//重复调用会被忽略
ws.setAppCachePath(path);
/**
 *设置应用缓存内容的最大值。所传值会被近似为数据库支持的最近似值,因此这是一个指示值,而不是一个固定值。
 *所传值若小于数据库大小不会让数据库调整大小。默认值是MAX_VALUE,建议将默认值设置为最大值。
 */
ws.setAppCacheMaxSize();

WebViewClient

如果页面中链接,如果希望点击链接继续在当前应用中响应,而不是新开Android的系统浏览器中响应该链接,必须覆盖 WebViewWebViewClient对象

代码语言:javascript复制
mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

除此之外,还有其他的可重写的方法我们来看一看

代码语言:javascript复制
mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                //可以在这里显示loading加载等业务
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                //可以关闭loading加载等业务
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                //加载页面的服务器出现错误时调用 error.getErrorCode()对应异常码,可以进行业务处理
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                //默认是不处理https请求的页面显示空白,尤其在加载的url域名配置https后,常见的是url中的图片看不见了,就是因为https的默认不处理导致,配置如下解决
                handler.proceed();
            }
        });

WebChromeClient

代码语言:javascript复制
mWebView.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                //监听加载进度,通常有进度条需要在这里设置进度
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                //在此可以获取标题
            }

        });

实例演示

这里我们来演示一个带进度条的加载 url的实例。

因为 WebView需要加载网页需要网络访问权限,在你的 AndroidManifest.xml中检查一下权限

代码语言:javascript复制
<uses-permission android:name="android.permission.INTERNET"/>

增加一个 activity_webview.xml布局如下:

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <WebView
        android:id="@ id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ProgressBar
        android:id="@ id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="10dp" />

</RelativeLayout>

Activity中编写代码如下:

代码语言:javascript复制
/**
 * WebView必知必会的基础
 *
 * @author xmkh
 */
public class WebViewActivity extends AppCompatActivity {
    private WebView mWebView;
    private ProgressBar mProgressbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        mWebView = findViewById(R.id.webview);
        mProgressbar = findViewById(R.id.progressBar);
        mProgressbar.setMax(100);
        //优先使用缓存:
        WebSettings ws = mWebView.getSettings();
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                //监听加载进度,通常有进度条需要在这里设置进度
                if (newProgress == 100) {
                    mProgressbar.setVisibility(View.GONE);
                } else {
                    mProgressbar.setProgress(newProgress);
                }
            }
        });
        mWebView.loadUrl("http://www.baidu.com");
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //点击返回上一页面,如果有多级页面历史,则回退到上一级而不是退出Activity
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }


    @Override
    protected void onDestroy() {
        //进来避免内存泄漏
        if (mWebView != null) {
            mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebView.clearHistory();
            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.destroy();
            mWebView = null;
        }
        super.onDestroy();
    }
}

大功告成,最终实现效果如下:

0 人点赞