WebView使用详解(二)——WebViewClient与经常使用事件监听

 

关闭
 

WebView使用详解(二)——WebViewClient与经常使用事件监听 

 分类:
 

目录(?)[+]java

 

前言:生活的艰难,更会激发对梦想的渴望,但艰难的生活却每每会成为梦想的绊脚石

mysql

相关文章:
一、《WebView使用详解(一)——Native与JS相互调用(附JadX反编译)》
二、《WebView使用详解(二)——WebViewClient与经常使用事件监听》
三、《WebView使用详解(三)——WebChromeClient与LoadData补充》linux

 

上篇给你们简单讲了Webview中Native代码与JS相互调用的方法,这篇咱们再讲讲有关各类拦截与处理的东东。android

1、WebViewClient

一、概述

前面咱们虽然实现了交互,但可能咱们会有一个很简单的需求,就是在开始加载网页的时候显示进度条,加载结束之后隐藏进度条,这要怎么作? 
这些简单的需求,Android开发的老人们确定都已经想到了,这些有关各类事件的回调都被封装在WebViewClient类中了,在WebViewClient中有各类的回调方法,就是在某个事件发生时供咱们监听 
使用方法以下:

 

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  4.         super.onPageStarted(view, url, favicon);  
  5.         Log.d(TAG,"onPageStarted");  
  6.     }  
  7.   
  8.     @Override  
  9.     public void onPageFinished(WebView view, String url) {  
  10.         super.onPageFinished(view, url);  
  11.         Log.d(TAG,"onPageFinished");  
  12.     }  
  13. });  
直接调用WebView.setWebViewClient方法便可设置WebViewClient回调,这里重写的两个函数,onPageStarted会在WebView开始加载网页时调用,onPageFinished会在加载结束时调用。这两个函数就能够完成咱们开篇时的需求:在开始加载时显示进度条,在结束加载时隐藏进度条。

二、WebViewClient中函数概述

在WebViewClient中除了上面咱们列举出的onPageStarted、onPageFinished还有不少其它函数,分别是:
[java]  view plain  copy
  1. /** 
  2.  * 在开始加载网页时会回调 
  3.  */  
  4. public void onPageStarted(WebView view, String url, Bitmap favicon)   
  5. /** 
  6.  * 在结束加载网页时会回调 
  7.  */  
  8. public void onPageFinished(WebView view, String url)  
  9. /** 
  10.  * 拦截 url 跳转,在里边添加点击连接跳转或者操做 
  11.  */  
  12. public boolean shouldOverrideUrlLoading(WebView view, String url)  
  13. /** 
  14.  * 加载错误的时候会回调,在其中可作错误处理,好比再请求加载一次,或者提示404的错误页面 
  15.  */  
  16. public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)  
  17. /** 
  18.  * 当接收到https错误时,会回调此函数,在其中能够作错误处理 
  19.  */  
  20. public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)  
  21. /** 
  22.  * 在每一次请求资源时,都会经过这个函数来回调 
  23.  */  
  24. public WebResourceResponse shouldInterceptRequest(WebView view,  
  25.         String url) {  
  26.     return null;  
  27. }  
上面的方法比较多,咱们一个个来看

三、WebViewClient之onPageStarted与onPageFinished

onPageStarted:通知主程序页面当前开始加载。该方法只有在加载main frame时加载一次,若是一个页面有多个frame,onPageStarted只在加载main frame时调用一次。也意味着若内置frame发生变化,onPageStarted不会被调用,如:在iframe中打开url连接。 
onPageFinished:通知主程序页面加载结束。方法只被main frame调用一次。 
咱们就利用上面的想法来举个例子:开始加载时显示加载圆圈,结束加载时隐藏加载圆圈
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  16.         mWebView.setWebViewClient(new WebViewClient(){  
  17.   
  18.             @Override  
  19.             public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  20.                 mWebView.loadUrl(url);  
  21.                 return true;  
  22.             }  
  23.   
  24.             @Override  
  25.             public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  26.                 super.onPageStarted(view, url, favicon);  
  27.                 mProgressDialog.show();  
  28.             }  
  29.   
  30.             @Override  
  31.             public void onPageFinished(WebView view, String url) {  
  32.                 super.onPageFinished(view, url);  
  33.                 mProgressDialog.hide();  
  34.             }  
  35.         });  
  36.     }  
  37. }  
效果图以下:

 

从效果图中能够明显看出,在加载页面的时候会显示圆形加载框,在加载成功之后会隐藏加载框。程序员

四、WebViewClient之shouldOverrideUrlLoading

该函数的完整声明以下:

 

 

[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url)  
这个函数会在加载超连接时回调过来;因此经过重写shouldOverrideUrlLoading,能够实现对网页中超连接的拦截; 
返回值是boolean类型,表示是否屏蔽WebView继续加载URL的默认行为,由于这个函数是WebView加载URL前回调的,因此若是咱们return true,则WebView接下来就不会再加载这个URL了,全部处理都须要在WebView中操做,包含加载。若是咱们return false,则系统就认为上层没有作处理,接下来仍是会继续加载这个URL的。WebViewClient默认就是return false的:
[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  2.        return false;  
  3. }  

(1)、如何在WebView中加载在线网址 

在上一篇中,咱们提到,若是要在WebView中加载在线网址,必须重写WebViewClient 
如今网上铺天盖地的都是重写shouldOverrideUrlLoading来将URL加载进WebView,但在用多了WebView之后会发现,直接下面这样写,就能够实如今WebVIew中加载网页:
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient());  
  16.   
  17.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  18.     }  
  19. }  
效果图以下:

 

从效果图中能够看出即仅仅设置WebViewClient对象,使用它的默认回调就能够实如今WebView中加载在线URL了:web

 

[plain]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient());  

(2)、shouldOverrideUrlLoading用途 

因为每次超连接在加载前都会先走shouldOverrideUrlLoading回调,因此咱们若是想拦截某个URL,将其转换成其它URL能够在这里作。 
好比,咱们拦截全部包含“blog.csdn.net”的地址,将其替换成”www.baidu.com”: 
效果图以下:

 

代码以下:面试

 

[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient(){  
  16.             @Override  
  17.             public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  18.                 if (url.contains("blog.csdn.net")){  
  19.                     view.loadUrl("http://www.baidu.com");  
  20.                 }else {  
  21.                     view.loadUrl(url);  
  22.                 }  
  23.                 return true;  
  24.             }  
  25.         });  
  26.   
  27.         mWebView.loadUrl("http://blog.csdn.net/harvic880925");  
  28.     }  
  29. }  
最关键的位置在:
[java]  view plain  copy
  1. public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  2.    if (url.contains("blog.csdn.net")){  
  3.         view.loadUrl("http://www.baidu.com");  
  4.     }else {  
  5.         view.loadUrl(url);  
  6.     }  
  7.    return true;  
  8. }  
若是在当前webview加载的url中包含“blog.csdn.net”,则将其转换成”www.baidu.com” 
这里须要很是注意的是:若是咱们在shouldOverrideUrlLoading中return true,就表示告诉系统咱们已经拦截了URL并作处理,不须要再触发系统默认的行为()在WebView中加载URL;因此对于其它URL咱们须要在else里从新调用view.loadUrl(url)来加载;否则WebView将会白屏,由于这个URL根本就没有加载进WebView,在shouldOverrideUrlLoading这就被咱们拦截掉了。 
那么问题来了,在咱们return true了之后,WebView还会请求网络吗?咱们来抓下请求:

从请求中能够看到,咱们虽然拦截了”http://blog.csdn.net/harvic880925“可是仍然仍是会请求网络的。只是请求之后结果并无经过WebView加载。 
那问题来了,若是咱们return false呢,若是咱们return false的话,是不须要else语句的,由于系统默认会加载这个URL,因此上面的语句与下面的意义相等:

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  4.         if (url.contains("blog.csdn.net")){  
  5.             view.loadUrl("http://www.baidu.com");  
  6.         }  
  7.         return false;  
  8.     }  
  9. }      
因此相对而言,咱们使用return false好像更方便,只须要对须要拦截的URL进行拦截,拦截之后,让WebView处理默认操做便可。 
因此结论来了:
在利用shouldOverrideUrlLoading来拦截URL时,若是return true,则会屏蔽系统默认的显示URL结果的行为,不须要处理的URL也须要调用loadUrl()来加载进WebVIew,否则就会出现白屏;若是return false,则系统默认的加载URL行为是不会被屏蔽的,因此通常建议你们return false,咱们只关心咱们关心的拦截内容,对于不拦截的内容,让系统本身来处理便可。

五、WebViewClient之onReceivedError

onReceivedError的完整声明以下:

 

 

[java]  view plain  copy
  1. public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)  
加载错误的时候会产生这个回调,在其中可作错误处理,好比咱们能够加载一个错误提示页面 
这里有四个参数:
  • WebView view:当前的WebView实例
  • int errorCode:错误码
  • String description:错误描述
  • String failingUrl:当前出错的URL
咱们能够先写一个错误提示的本地页面:(error.html)
[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>Title</title>  
  6. </head>  
  7. <body>  
  8.     <h1 id="h">啊哈,出错了……</h1>  
  9. </body>  
  10. </html>  
而后在加载返回错误时,从新加载错误页面
[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  
  4.         super.onReceivedError(view, errorCode, description, failingUrl);  
  5.         mWebView.loadUrl("file:///android_asset/error.html");  
  6.     }  
  7. });  
效果图以下:

 

 

源码在文章底部给出

六、WebViewClient之onReceivedSslError

咱们知道HTTPS协议是经过SSL来通讯的,因此当使用HTTPS通讯的网址(以https://开头的网站)出现错误时,就会经过onReceivedSslError回调通知过来,它的函数声明为:

 

 

[java]  view plain  copy
  1. /** 
  2.  * 当接收到https错误时,会回调此函数,在其中能够作错误处理 
  3.  */  
  4. public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)  
  • WebView view:当前的WebView实例
  • SslErrorHandler handler:当前处理错误的Handler,它只有两个函数SslErrorHandler.proceed()和SslErrorHandler.cancel(),SslErrorHandler.proceed()表示忽略错误继续加载,SslErrorHandler.cancel()表示取消加载。在onReceivedSslError的默认实现中是使用的SslErrorHandler.cancel()来取消加载,因此一旦出来SSL错误,HTTPS网站就会被取消加载了,若是想忽略错误继续加载就只有重写onReceivedSslError,并在其中调用SslErrorHandler.proceed()
  • SslError error:当前的的错误对象,SslError包含了当前SSL错误的基本全部信息,你们本身去看下它的方法吧,这里就再也不展开了。

示例(1)、默认加载SSL出错的网站——出现空白页面 

咱们先举个例子来看下默认状况下加载SSL有错的网站,WebView的表现是怎样的:(12306是经过Https协议来传输的,可是它的SSL证书是有问题的,因此咱们就以12306网站为例)
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.         mWebView.setWebViewClient(new WebViewClient(){  
  16.             @Override  
  17.             public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  18.                 super.onReceivedSslError(view, handler, error);  
  19.                 Log.e(TAG,"sslError:"+error.toString());  
  20.             }  
  21.   
  22.         mWebView.loadUrl("https://www.12306.cn/");  
  23.     }  
  24. }  
在这里仅仅重写onReceivedSslError,并调用super.onReceivedSslError(view, handler, error);来调用默认的处理方式,而后把错误日志打出来:

错误日志以下:

 

示例(2)、使用SslErrorHandler.proceed()来继续加载

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  4. //      必定要注释掉!      
  5. //      super.onReceivedSslError(view, handler, error);  
  6.         handler.proceed();  
  7.         Log.e(TAG,"sslError:"+error.toString());  
  8.     }  
  9. });  
这里作了两个改变: 
第一:注释掉super.onReceivedSslError(view, handler, error);,取消系统的默认行为,咱们看源码,能够发如今WebViewClient中onReceivedSslError的默认实现是这样的:
[java]  view plain  copy
  1. public void onReceivedSslError(WebView view, SslErrorHandler handler,  
  2.         SslError error) {  
  3.     handler.cancel();  
  4. }  
因此默认是取消继续加载的,因此咱们必须注释掉super.onReceivedSslError(view, handler, error)来取消这个默认行为! 
第二:调用handler.proceed();来忽略错误继续加载页面。 
因此此时的效果图为:

示例(3):在SSL发生错误时,onReceivedError会被回调吗?——不会 

你们可能还有一个疑问:当SSL发生错误时,咱们说会回调onReceivedSslError,咱们前面还说了一个出错时会回调的函数:onReceivedError,那么问题来了,当出现SSL错误时onReceivedError会被回调吗? 
答案是不会的,咱们来作个实验:

 

[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
  4. //                super.onReceivedSslError(view, handler, error);  
  5.         handler.proceed();  
  6.         Log.e(TAG,"sslError:"+error.toString());  
  7.     }  
  8.   
  9.     @Override  
  10.     public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  
  11.         super.onReceivedError(view, errorCode, description, failingUrl);  
  12.         Log.e(TAG,"onReceivedError:"+errorCode+"  "+description);  
  13.     }  
  14. });  

在代码中咱们同时使用onReceivedSslError和onReceivedError来接收错误,看下在出错时,哪一个函数中会打出LOG,结果的日志以下:

 

从日志中明显能够看出,只有onReceivedSslError的接收日志,因此在SSL出错时,是不会触发onReceivedError回调的
因此对于onReceivedSslError结论来了:
当出现SSL错误时,WebView默认是取消加载当前页面,只有去掉onReceivedSslError的默认操做,而后添加SslErrorHandler.proceed()才能继续加载出错页面
当HTTPS传输出现SSL错误时,错误会只经过onReceivedSslError回调传过来算法

七、WebViewClient之shouldInterceptRequest

在每一次请求资源时,都会经过这个函数来回调,好比超连接、JS文件、CSS文件、图片等,也就是说浏览器中每一次请求资源时,都会回调回来,不管任何资源!可是必须注意的是shouldInterceptRequest函数是在非UI线程中执行的,在其中不能直接作UI操做,若是须要作UI操做,则须要利用Handler来实现,该函数声明以下:

 

 

[java]  view plain  copy
  1. public WebResourceResponse shouldInterceptRequest(WebView view,  
  2.         String url) {  
  3.     return null;  
  4. }  
该函数会在请求资源前调用,咱们能够经过返回WebResourceResponse的处理结果来让WebView直接使用咱们的处理结果。若是咱们不想处理,则直接返回null,系统会继续加载该资源。 
利用这个特性,咱们能够解决一个需求:假如网页中须要加载本地的图片,咱们就能够经过拦截shouldInterceptRequest,并返回结果便可 
好比下面的一段HTML代码中,img字段加载图片的地址是:http://localhost/qijian.png,这是我自定义的一个网址,在Android中,当发现要加载这个地址的资源时,咱们将它换成本地的图片
[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>Title</title>  
  6. </head>  
  7. <body>  
  8.     <h1 id="h">欢迎光临启舰的blog</h1>  
  9.     <img src="http://localhost/qijian.png"/>  
  10. </body>  
  11. </html>  
而后是Native代码:
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.   
  15.   
  16.         mWebView.setWebViewClient(new WebViewClient(){  
  17.             @Override  
  18.             public WebResourceResponse shouldInterceptRequest(WebView view, String url) {  
  19.                 try {  
  20.                     if (url.equals("http://localhost/qijian.png")) {  
  21.                         AssetFileDescriptor fileDescriptor =  getAssets().openFd("s07.jpg");  
  22.                         InputStream stream = fileDescriptor.createInputStream();  
  23.                         WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
  24.                         return response;  
  25.                     }  
  26.                 }catch (Exception e){  
  27.                     Log.e(TAG,e.getMessage());  
  28.                 }  
  29.                 return super.shouldInterceptRequest(view, url);  
  30.             }  
  31.         });  
  32.   
  33.         mWebView.loadUrl("file:///android_asset/web.html");  
  34. }          
这里代码比较容易理解,当发现当前加载资源的url是咱们自定义的http://localhost/qijian.png时,就直接将本地的图片s07.jpg做为结果返回。有关使用WebResourceResponse来构造结果的方法,我这里就再也不展开了,内容实在是太多了,想具体了解针对不一样状况如何返回结果的话,本身搜下相关资料吧。 
结果图以下:

 

 

七、WebViewClient之其他函数

上面讲了经常使用的大部分函数,还些一些函数,并不怎么用,这里因为篇幅有限就再也不讲了,把函数声明和做用列出来供你们参考

 

 

[java]  view plain  copy
  1. /** 
  2.  * 在加载页面资源时会调用,每个资源(好比图片)的加载都会调用一次 
  3.  */  
  4. public void onLoadResource(WebView view, String url)   
  5.  /** 
  6.  *  (WebView发生改变时调用)  
  7.  *  能够参考http://www.it1352.com/191180.html的用法 
  8.  */  
  9.  public void onScaleChanged(WebView view, float oldScale, float newScale)  
  10.  /** 
  11.  * 重写此方法才可以处理在浏览器中的按键事件。 
  12.  * 是否让主程序同步处理Key Event事件,如过滤菜单快捷键的Key Event事件。 
  13.  * 若是返回true,WebView不会处理Key Event, 
  14.  * 若是返回false,Key Event老是由WebView处理。默认:false 
  15.  */  
  16. public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)  
  17.  /** 
  18.  * 是否重发POST请求数据,默认不重发。 
  19.  */  
  20. onFormResubmission(WebView view, Message dontResend, Message resend)  
  21.  /** 
  22.  * 更新访问历史 
  23.  */  
  24. doUpdateVisitedHistory(WebView view, String url, boolean isReload)  
  25.  /** 
  26.  * 通知主程序输入事件不是由WebView调用。是否让主程序处理WebView未处理的Input Event。 
  27.  * 除了系统按键,WebView老是消耗掉输入事件或shouldOverrideKeyEvent返回true。 
  28.  * 该方法由event 分发异步调用。注意:若是事件为MotionEvent,则事件的生命周期只存在方法调用过程当中, 
  29.  * 若是WebViewClient想要使用这个Event,则须要复制Event对象。 
  30.  */  
  31. onUnhandledInputEvent(WebView view, InputEvent event)  
  32.  /** 
  33.  * 通知主程序执行了自动登陆请求。 
  34.  */  
  35. onReceivedLoginRequest(WebView view, String realm, String account, String args)  
  36. /** 
  37.  * 通知主程序:WebView接收HTTP认证请求,主程序可使用HttpAuthHandler为请求设置WebView响应。默认取消请求。 
  38.  */  
  39. onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)  
  40. /** 
  41.  * 通知主程序处理SSL客户端认证请求。若是须要提供密钥,主程序负责显示UI界面。 
  42.  * 有三个响应方法:proceed(), cancel() 和 ignore()。 
  43.  * 若是调用proceed()和cancel(),webview将会记住response, 
  44.  * 对相同的host和port地址再也不调用onReceivedClientCertRequest方法。 
  45.  * 若是调用ignore()方法,webview则不会记住response。该方法在UI线程中执行, 
  46.  * 在回调期间,链接被挂起。默认cancel(),即无客户端认证 
  47.  */  
  48. onReceivedClientCertRequest(WebView view, ClientCertRequest request)<span style="color:#006600;">  
  49. </span>  

2、其它事件处理

上面讲了有关WebViewClient的用法,但其中还有一些小问题是WebViewClient没法解决的,好比返回按键、滚动事件监听等,下面咱们就这些问题来跟你们作下探讨

一、返回按键

若是用webview点连接看了不少页之后,若是不作任何处理,点击系统“Back”键,整个浏览器会调用finish()而结束自身,若是但愿浏览的网页回退而不是退出浏览器,须要在当前Activity中处理并消费掉该Back事件。 覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法。
[java]  view plain  copy
  1. public class MyActivity extends Activity {  
  2.     private WebView mWebView;  
  3.   
  4.     private ProgressDialog mProgressDialog;  
  5.     private String TAG = "qijian";  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);  
  10.   
  11.         mWebView = (WebView)findViewById(R.id.webview);  
  12.         mProgressDialog = new ProgressDialog(this);  
  13.         mWebView.getSettings().setJavaScriptEnabled(true);  
  14.         mWebView.setWebViewClient(new WebViewClient());  
  15.   
  16.         mWebView.loadUrl("http://blog.csdn.net/harvic880925/");  
  17.     }  
  18.   
  19.     @Override  
  20.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  21.          //改写物理返回键的逻辑  
  22.         if(keyCode==KeyEvent.KEYCODE_BACK) {  
  23.             if(mWebView.canGoBack()) {  
  24.                 mWebView.goBack();//返回上一页面   
  25.                 return true;  
  26.             } else {  
  27.                 System.exit(0);//退出程序   
  28.             }  
  29.         }  
  30.         return super.onKeyDown(keyCode, event);  
  31.     }  
  32. }  
在未重写onKeyDown前的效果图:点击回退按钮,整个Activity就销毁了

 

重写onKeyDown后的效果图:
sql

可见在重写onKeyDown后,点击回退按钮时,就会回退到WebView的上一个页面。

二、滚动事件监听

咱们都知道监听滚动事件通常都是设置setOnScrollChangedListener,惋惜的是 WebView并无给咱们提供这样的方法,可是咱们能够重写WebView,覆盖里面的一个方法: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} 而后再对外提供一个接口,示例代码以下:

 

 

[java]  view plain  copy
  1. public class MyWebView extends WebView {  
  2.   
  3.     private OnScrollChangedCallback mOnScrollChangedCallback;  
  4.   
  5.     public MyWebView(Context context) {  
  6.         super(context);  
  7.     }  
  8.   
  9.     public MyWebView(Context context, AttributeSet attrs) {  
  10.         super(context, attrs);  
  11.     }  
  12.   
  13.     public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {  
  14.         super(context, attrs, defStyleAttr);  
  15.     }  
  16.   
  17.     @Override  
  18.     protected void onScrollChanged(int l, int t, int oldl, int oldt) {  
  19.         super.onScrollChanged(l, t, oldl, oldt);  
  20.         if (mOnScrollChangedCallback != null) {  
  21.             mOnScrollChangedCallback.onScroll(l,t,oldl,oldt);  
  22.         }  
  23.     }  
  24.   
  25.     public OnScrollChangedCallback getOnScrollChangedCallback() {  
  26.         return mOnScrollChangedCallback;  
  27.     }  
  28.   
  29.     public void setOnScrollChangedCallback(  
  30.             final OnScrollChangedCallback onScrollChangedCallback) {  
  31.         mOnScrollChangedCallback = onScrollChangedCallback;  
  32.     }  
  33.   
  34.     public static interface OnScrollChangedCallback {  
  35.         public void onScroll(int left,int top ,int oldLeft,int oldTop);  
  36.     }  
  37. }  
这段代码难度不大,就再也不细讲了。

三、如何强制使用外部浏览器打开网页

若是不想在 webview 中显示网页,而是直接跳转到浏览器的话,能够像下边那样调用。
[java]  view plain  copy
  1. Uri uri = Uri.parse("http://www.example.com");   
  2. Intent intent = new Intent(Intent.ACTION_VIEW, uri);   
  3. startActivity(intent);  
这里是使用隐式Intent的方式来启用外部应用,有关隐式Intent的知识,能够参考: 
《intent详解(一)》 
《intent详解(二)》

好了,这篇文章就到这里了,下篇文章给你们继续讲解有关WebView的知识。

 

若是本文有帮到你,记得加关注哦

源码下载地址:http://download.csdn.net/detail/harvic880925/9534186

请你们尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/51523983 谢谢

 

若是你喜欢个人文章,那么你将会更喜欢个人微信公众号,将按期推送博主最新文章与收集干货分享给你们(一周一次)

 

 
24
0
 
 
 

 

 
查看评论
12楼  bruce_lv 4天前 12:19发表  [回复]
[java]  view plain  copy
  1. mWebView.setWebViewClient(new WebViewClient(){  
  2.     @Override  
  3.     public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  4.         if (url.contains("csdn")){  
  5.             view.loadUrl("baidu");  
  6.         }  
  7.         return false;  
  8.     }  
  9. }    

此时除了请求baidu还会请求CSDN吗?
11楼  moyisiha 2017-06-23 10:11发表  [回复]
请问:
假如JS中返回按钮直接调用了系统window.histroy(-1)
这个时候,webview能监听到这个信号吗
10楼  贝澪 2017-02-24 09:47发表  [回复]
真的很是详细,感谢帮助!
9楼  xlx602158474 2016-12-27 17:45发表  [回复]
楼主上面讲到当加载https的网址时,出现SSL错误时,若是想要忽略掉该错误,要调用handler.process()方法,并必定要删除掉super.onReceivedSslError(view, handler, error)方法,但我没有删除那个方法,网页也加载出来了,这是为何???。注:网址是https的,而且必须调用handler.process()才能加载出网页。
8楼  Jugg_VS_Spe_细节多到爆炸 2016-12-14 16:45发表  [回复]
厉害厉害,感谢帮助!
7楼  wangyao20 2016-12-14 16:40发表  [回复]
楼主,你好 若是我想在loadurl再接收广播怎么办,如今cordovaActivity接收不了广播,好比蓝牙按键广播
6楼  xc87607536 2016-09-27 15:36发表  [回复]
我是来看博主的本地图片的
5楼  zyj_9327 2016-08-19 17:28发表  [回复]
灰常感谢楼主的分享,很清晰很条理!学习了!
楼主好棒!!!!
4楼  xiaozilong168 2016-07-22 19:21发表  [回复]
大神请教
WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
return response;

若是我想用一个URL网址替换本来要将要打开的URL网址怎么办呢?
Re:  Look19 2016-12-06 10:39发表  [回复]
回复xiaozilong168:群主讲的不是有拦截的,直接在拦截里面操做就能够了~
3楼  xiaozilong168 2016-07-22 19:20发表  [回复]
大神,求教。。
WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);  
return response;

若是我是想用一个网络上的图片或网页地址替换原有URL怎么作呢?而不是从本地读一个文件出来替换。
2楼  Hankins_Pan 2016-06-07 13:18发表  [回复]
博主总结的很是细致,条例清晰,结构规整,演示明了。学习了!感谢分享!
1楼  哆啦miss梦 2016-05-31 22:40发表  [回复]
大神,能够换成Markdown编辑了,看起感受舒服一些
 
* 以上用户言论只表明其我的观点,不表明CSDN网站的观点或立场
 
 
 
 
    我的资料
 
 
1  1
    • 访问:3855788次
    • 积分:24247
    • 等级: 
    • 排名:第256名
    • 原创:231篇
    • 转载:35篇
    • 译文:0篇
    • 评论:2581条
    个人新浪微博
    交流群来啦
新建了一个交流群,你们能够加入
       

QQ群号一(已满):304235209
QQ群号二:554244703
       


博主须要你!!!
       


个人微信公众号
       

      关注博主最新动态和干货分享,一周一次 
       

      下面是我作IT技术面试辅导的公众号,旨在为你们提供技术面试相关的资料与支持 

       
    博客专栏
《Animation动画详解》

文章:13篇

阅读:236559
    文章存档
    最新评论
 
 
相关文章
相关标签/搜索