webview最全面总结(二)全面介绍webview用法

简单介绍

为了方便开发者实现在app内展示网页并与网页交互的需求,Android SDK提供了WebView组件
它有如下功能:

  • 显示和渲染Web页面
  • 直接使用html文件(网络上或本地assets中)作布局
  • 可和JavaScript交互调用
  • WebView控件功能强大,除了具有一般View的属性和设置外,还可以对url请求、页面加载、渲染、页面交互进行强大的处理。

基本使用

下面简单介绍下WebView的基本使用:

首先新建一个工程,在layout文件里放入一个WebView控件

<?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"
   >

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

    </WebView>
</RelativeLayout>

然后在Activity初始化方法里写入如下代码:

  String url = "https://www.kkj.cn";

  WebView webView = (WebView) findViewById(R.id.web_view);
  webView.loadUrl(url);
  WebSettings webSettings = webview.getSettings();  
  webSettings.setJavaScriptEnabled(true);     
  webSettings.setJavaScriptCanOpenWindowsAutomatically(true);   

不要忘了在AndroidManifest声明访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

然后bingo运行,我们会发现,纳尼,居然在外部的默认浏览器中打开了这个链接。

因为默认情况下,一个WebView提供的是不像浏览器的控件,没有开启JavaScript并且忽略网页错误。如果你的目的是仅仅显示一些HTML作为你的UI的一部分,那显示可能是没有问题的(显示正常),用户仅仅阅读网页而不需要与之交互,并且网页也不需要和用户交互。

如果你想要在webview内部打开,则需要自定义WebChromeClient 方法。
一般我们重写最多的就是shouldOverrideUrlLoading()、onPageStarted()、onPageFinished()问题。

webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

             return false;
            }
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                //webview页面加载开始时就会执行此方法、一般用作重定向时的初始化工作
                //该方法在WebView开始加载页面且仅在Main frame loading(即整页加载)时回调,一次Main frame的加载只会回调该方法一次。我们可以在这个方法里设定开启一个加载的动画,告诉用户程序在等待网络的响应。
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                //该方法只在WebView完成一个页面加载时调用一次(同样也只在Main frame loading时调用),我们可以可以在此时关闭加载动画,进行其他操作。

            }
        });

这样重写之后,我们就能在webview里面打开我们想要打开的页面了。然而,我们发现,当我们在我们打开页面的页面中继续跳转时候,再按系统返回键,会发现,直接关闭了webview,这显然不是我们想要的结果。

  @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //这是一个监听用的按键的方法,keyCode 监听用户的动作,如果是按了返回键,同时Webview要返回的话,WebView执行回退操作,因为mWebView.canGoBack()返回的是一个Boolean类型,所以我们把它返回为true
        if(keyCode==KeyEvent.KEYCODE_BACK&&webview.canGoBack()){
            webview.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

重写返回键之后就能实现,在网页中返回上一步。

详细看一下webview的各个知识点。

加载方式

1、loadUrl(String url)

用的最多的加载方式,

des:Load the given url.
as: webView.loadUrl(“http://www.kkj.cn/“); //加载网络网页
webView.loadUrl(“file:///android_asset/html/index.html”); //加载本地assert目录下网页
webView.loadUrl(“content://com.Android.htmlfileprovider/sdcard/kris.html”); // 加载SD卡html

2、loadData(String data, String mimeType, String encoding)
des:Load the given data into the WebView.
as:
String summary = “You scored 192 points.”;
webview.loadData(summary, “text/html”, null);
如果后台给的数据是包含html的字符串,则需要用这种方式进行加载,这种方式省流量,速度快,但是需要注意编码问题。
loadData()中的html data不能包含’#’,’%’,’\’,’?’四种特殊字符

3、loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)

des:Load the given data into the WebView, use the provided URL as the base URL for the content.

webview的设置

    WebSettings webSettings = webview.getSettings();

    //支持js事件
    webSettings.setJavaScriptEnabled(true);
    /* 设置为true表示支持使用js打开新的窗口 */
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

    /* 设置为使用webview推荐的窗口 */
    webSettings.setUseWideViewPort(true);
    /* 设置网页自适应屏幕大小 ---这个属性应该是跟上面一个属性一起用 */
    webSettings.setLoadWithOverviewMode(true);

    /* 设置是否允许webview使用缩放的功能,我这里设为false,不允许 */
    webSettings.setBuiltInZoomControls(false);
    webSettings.setBuiltInZoomControls(true); //显示或不显示缩放按钮(wap网页不支持)。
    webSettings.setSupportMultipleWindows(true);//设置WebView是否支持多窗口。

    webSettings.setAppCacheEnabled(true); //启用或禁用应用缓存。
    webSettings.setAppCachePath("");//设置应用缓存路径,这个路径必须是可以让app写入文件的。该方法应该只被调用一次,重复调用会被无视~
    webSettings.setCacheMode(LOAD_DEFAULT);//用来设置WebView的缓存模式。当我们加载页面或从上一个页面返回的时候,会按照设置的缓存模式去检查并使用(或不使用)缓存。

篇幅限制,仅列了一些最常用的设置,webview还可以设置更多内容,存储,默认字体大小,默认字符编码等等,
具体可以参考,史上最全的WebSettings说明

  对于webview也有
    webView.setHorizontalScrollBarEnabled(false);//水平不显示  
    webView.setVerticalScrollBarEnabled(false); //垂直不显示   
    webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);// 隐藏滚动条 
    webView.requestFocus();      设置是否获取焦点    
    webView.requestFocusFromTouch();  

WebViewClient

主要帮助WebView处理各种通知、请求事件(例如,点击链接时候如何显示界面,页面开始加载,加载完毕之后

webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
             return false;
            }
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                //webview页面加载开始时就会执行此方法、一般用作重定向时的初始化工作
                //该方法在WebView开始加载页面且仅在Main frame loading(即整页加载)时回调,一次Main frame的加载只会回调该方法一次。我们可以在这个方法里设定开启一个加载的动画,告诉用户程序在等待网络的响应。
            }
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                //该方法只在WebView完成一个页面加载时调用一次(同样也只在Main frame loading时调用),我们可以可以在此时关闭加载动画,进行其他操作。
            }
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                 super.onReceivedError(view, errorCode, description, failingUrl);
        // 这里进行无网络或错误处理,具体可以根据errorCode的值进行判断,
    }

shouldOverrideUrlLoading()方法分析

从实践中我们知道,当我们没有给WebView提供WebViewClient时,WebView如果要加载一个url会向ActivityManager寻求一个适合的处理者来加载该url(比如系统自带的浏览器),这通常是我们不想看到的。于是我们需要给WebView提供一个WebViewClient,并重写该方法返回true来告知WebView url的加载就在app中进行。这时便可以实现在app内访问网页
简单来说就是:

1、若没有设置 WebViewClient 则在点击链接之后由系统处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框。
2、若设置 WebViewClient 且该方法返回 true ,则说明由应用的代码处理该 url,WebView 不处理。
3、若设置 WebViewClient 且该方法返回 false,则说明由 WebView 处理该 url,即用 WebView 加载该 url。

WebChromeClient

辅助WebView处理Javascript的对话框、网站图标、网站Title、加载进度等

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        // 获得网页的加载进度 newProgress为当前加载百分比
        super.onProgressChanged(view, newProgress);
    }
    @Override
    public void onReceivedTitle(WebView view, String title) {
        // 获取网页的title,客户端可以在这里动态修改页面的title
        // 另外,当加载错误时title为“找不到该网页”
        super.onReceivedTitle(view, title);
    }
});

js的交互

webView.addJavascriptInterface()

通过addJavascriptInterface(Object, String)方法注入Java对象到WebView。这个方法允许你注入一个Java对象到网页的JavaScript 的上下文,以便通过页面中的JavaScript调用。

简单粗暴时候可以这样写:

myWebView.addJavascriptInterface(new JSInterface(){                    
    @JavascriptInterface 
    public String methodA(){
            return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceId();
        }

   @JavascriptInterface
    public void methodB(String webMessage) {    }
    }, "Android");

方法可能会很多,所以我们要学会优雅一些;

mWebView.addJavascriptInterface(new JSInterface(), "Android");  //model是自定义的,随便起。
JSInterface对象:
public class JSInterface {

    @JavascriptInterface
    public void methodA() {    }

    @JavascriptInterface
    public void methodB(String webMessage) {    }
}

ps:SDK>=17(Android4.2)以上,必须添加@JavascriptInterface声明,为避免因用户访问不安全网页导致js漏洞盗窃用户信息等不安全行为。

js调java:

Java对象到WebView之后,我们要在js里面调用 java方法。

所有调用的方法都要写在class JSInterface{ }中。

funtion a{
      winow.Android.methodA();   //可带参数
}

java调js:

在webview里面调用js方法:

  webview.loadUrl("javascript:alert()"); 

前进后退刷新

webview是否可以返回到上一页面 webView.canGoBack()

webview返回到上一页面 webView.goBack();

webview是否可以前进 webView.canGoForward()

webview前进 webView.goForward();

webview.reload(); 刷新

举个回退的简单例子简单说明

public boolean onKeyDown(int keyCode, KeyEvent event) {
     if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
         mWebView.goBack();
         return true;
     }
     return super.onKeyDown(keyCode, event);
 }

判断Webview是否滑动到顶部或底部

if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
    // 处于底端
}
if(webView.getScrollY() == 0){
    //处于顶部
}

getScrollY() //方法返回的是当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离.
getHeight()或者getBottom() //方法都返回当前WebView这个容器的高度
getContentHeight()返回的是整个html的高度,但并不等同于当前整个页面的高度,因为WebView有缩放功能,所以当前整个页面的高度实际上应该是原始html的高度再乘上缩放比例

webView的状态

//当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
//它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。


@Override
    protected void onPause() {
       webview.onPause();
       webview.pauseTimers();
       super.onPause();
    }
 @Override
    protected void onResume() {
       webview.onResume();//重新激活WebView为活跃状态,响应网页
       webview.resumeTimers();//恢复pauseTimers状态
       super.onResume();
    //当页面被失去焦点被切换到后台不可见状态,需要执行onPause
  //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    }

//销毁Webview
//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
//但是注意:webview调用destory时,webview仍绑定在Activity上
//这是由于自定义webview构建时传入了该Activity的context对象
//因此需要先从父容器中移除webview,然后再销毁webview:
rootLayout.removeView(webView); 
webView.destroy();
    @Override  
    public void onDestroy() {  
        if (mWebView != null) {  
            mWebView.destroy();  
            mWebView = null;  
        }  
        super.onDestroy();  
    }  

webview缓存

 webview的缓存有四种模式,根据自己的需要选择对应的缓存模式。
       WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
        //缓存模式如下:
        //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
        //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
        //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
        //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

缓存运用:

if (NetStatusUtil.isConnected(getApplicationContext())) {
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
} else {
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
}
//使用缓存需要开启这些webview的设置,并且设置缓存路径
webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true);   //开启 database storage API 功能
webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能

String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(cacheDirPath); //设置  Application Caches 缓存目录

清除缓存:

clearCache(true);   //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
clearHistory ()  //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
clearFormData ()  //这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值