关闭

启舰

当乌龟有了梦想……

 
 
2016-05-28 11:24 20083人阅读 评论(13) 收藏 举报
 分类:
5、andriod开发(148) 

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

目录(?)[+]

 

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

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

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

一、WebViewClient

1、概述

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

  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. @Override
  8. public void onPageFinished(WebView view, String url) {
  9. super.onPageFinished(view, url);
  10. Log.d(TAG,"onPageFinished");
  11. }
  12. });

直接调用WebView.setWebViewClient方法即可设置WebViewClient回调,这里重写的两个函数,onPageStarted会在WebView开始加载网页时调用,onPageFinished会在加载结束时调用。这两个函数就可以完成我们开篇时的需求:在开始加载时显示进度条,在结束加载时隐藏进度条。

2、WebViewClient中函数概述

在WebViewClient中除了上面我们列举出的onPageStarted、onPageFinished还有很多其它函数,分别是:

  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. }

上面的方法比较多,我们一个个来看

3、WebViewClient之onPageStarted与onPageFinished

onPageStarted:通知主程序页面当前开始加载。该方法只有在加载main frame时加载一次,如果一个页面有多个frame,onPageStarted只在加载main frame时调用一次。也意味着若内置frame发生变化,onPageStarted不会被调用,如:在iframe中打开url链接。 
onPageFinished:通知主程序页面加载结束。方法只被main frame调用一次。 
我们就利用上面的想法来举个例子:开始加载时显示加载圆圈,结束加载时隐藏加载圆圈

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.loadUrl("http://blog.csdn.net/harvic880925");
  13. mWebView.setWebViewClient(new WebViewClient(){
  14. @Override
  15. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  16. mWebView.loadUrl(url);
  17. return true;
  18. }
  19. @Override
  20. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  21. super.onPageStarted(view, url, favicon);
  22. mProgressDialog.show();
  23. }
  24. @Override
  25. public void onPageFinished(WebView view, String url) {
  26. super.onPageFinished(view, url);
  27. mProgressDialog.hide();
  28. }
  29. });
  30. }
  31. }

效果图如下:

从效果图中可以明显看出,在加载页面的时候会显示圆形加载框,在加载成功以后会隐藏加载框。

4、WebViewClient之shouldOverrideUrlLoading

该函数的完整声明如下:

  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的:

  1. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  2. return false;
  3. }

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

在上一篇中,我们提到,如果要在WebView中加载在线网址,必须重写WebViewClient 
现在网上铺天盖地的都是重写shouldOverrideUrlLoading来将URL加载进WebView,但在用多了WebView以后会发现,直接下面这样写,就可以实现在WebVIew中加载网页:

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.setWebViewClient(new WebViewClient());
  13. mWebView.loadUrl("http://blog.csdn.net/harvic880925");
  14. }
  15. }

效果图如下:

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

  1. mWebView.setWebViewClient(new WebViewClient());

(2)、shouldOverrideUrlLoading用途

由于每次超链接在加载前都会先走shouldOverrideUrlLoading回调,所以我们如果想拦截某个URL,将其转换成其它URL可以在这里做。 
比如,我们拦截所有包含“blog.csdn.net”的地址,将其替换成”www.baidu.com”: 
效果图如下:

代码如下:

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.setWebViewClient(new WebViewClient(){
  13. @Override
  14. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  15. if (url.contains("blog.csdn.net")){
  16. view.loadUrl("http://www.baidu.com");
  17. }else {
  18. view.loadUrl(url);
  19. }
  20. return true;
  21. }
  22. });
  23. mWebView.loadUrl("http://blog.csdn.net/harvic880925");
  24. }
  25. }

最关键的位置在:

  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,所以上面的语句与下面的意义相等:

  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,我们只关心我们关心的拦截内容,对于不拦截的内容,让系统自己来处理即可。

5、WebViewClient之onReceivedError

onReceivedError的完整声明如下:

  1. public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)

加载错误的时候会产生这个回调,在其中可做错误处理,比如我们可以加载一个错误提示页面 
这里有四个参数:

  • WebView view:当前的WebView实例
  • int errorCode:错误码
  • String description:错误描述
  • String failingUrl:当前出错的URL

我们可以先写一个错误提示的本地页面:(error.html)

  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>

然后在加载返回错误时,重新加载错误页面

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

效果图如下:

源码在文章底部给出

6、WebViewClient之onReceivedSslError

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

  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网站为例)

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.setWebViewClient(new WebViewClient(){
  13. @Override
  14. public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
  15. super.onReceivedSslError(view, handler, error);
  16. Log.e(TAG,"sslError:"+error.toString());
  17. }
  18. mWebView.loadUrl("https://www.12306.cn/");
  19. }
  20. }

在这里仅仅重写onReceivedSslError,并调用super.onReceivedSslError(view, handler, error);来调用默认的处理方式,然后把错误日志打出来:

错误日志如下:

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

  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的默认实现是这样的:

  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会被回调吗? 
答案是不会的,我们来做个实验:

  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. @Override
  9. public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
  10. super.onReceivedError(view, errorCode, description, failingUrl);
  11. Log.e(TAG,"onReceivedError:"+errorCode+"  "+description);
  12. }
  13. });

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

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

7、WebViewClient之shouldInterceptRequest

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

  1. public WebResourceResponse shouldInterceptRequest(WebView view,
  2. String url) {
  3. return null;
  4. }

该函数会在请求资源前调用,我们可以通过返回WebResourceResponse的处理结果来让WebView直接使用我们的处理结果。如果我们不想处理,则直接返回null,系统会继续加载该资源。 
利用这个特性,我们可以解决一个需求:假如网页中需要加载本地的图片,我们就可以通过拦截shouldInterceptRequest,并返回结果即可 
比如下面的一段HTML代码中,img字段加载图片的地址是:http://localhost/qijian.png,这是我自定义的一个网址,在Android中,当发现要加载这个地址的资源时,我们将它换成本地的图片

  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代码:

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.setWebViewClient(new WebViewClient(){
  13. @Override
  14. public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
  15. try {
  16. if (url.equals("http://localhost/qijian.png")) {
  17. AssetFileDescriptor fileDescriptor =  getAssets().openFd("s07.jpg");
  18. InputStream stream = fileDescriptor.createInputStream();
  19. WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", stream);
  20. return response;
  21. }
  22. }catch (Exception e){
  23. Log.e(TAG,e.getMessage());
  24. }
  25. return super.shouldInterceptRequest(view, url);
  26. }
  27. });
  28. mWebView.loadUrl("file:///android_asset/web.html");
  29. }

这里代码比较容易理解,当发现当前加载资源的url是我们自定义的http://localhost/qijian.png时,就直接将本地的图片s07.jpg作为结果返回。有关使用WebResourceResponse来构造结果的方法,我这里就不再展开了,内容实在是太多了,想具体了解针对不同情况如何返回结果的话,自己搜下相关资料吧。 
结果图如下:

7、WebViewClient之其余函数

上面讲了常用的大部分函数,还些一些函数,并不怎么用,这里由于篇幅有限就不再讲了,把函数声明和作用列出来供大家参考

  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>

二、其它事件处理

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

1、返回按键

如果用webview点链接看了很多页以后,如果不做任何处理,点击系统“Back”键,整个浏览器会调用finish()而结束自身,如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity中处理并消费掉该Back事件。 覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法。

  1. public class MyActivity extends Activity {
  2. private WebView mWebView;
  3. private ProgressDialog mProgressDialog;
  4. private String TAG = "qijian";
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. mWebView = (WebView)findViewById(R.id.webview);
  10. mProgressDialog = new ProgressDialog(this);
  11. mWebView.getSettings().setJavaScriptEnabled(true);
  12. mWebView.setWebViewClient(new WebViewClient());
  13. mWebView.loadUrl("http://blog.csdn.net/harvic880925/");
  14. }
  15. @Override
  16. public boolean onKeyDown(int keyCode, KeyEvent event) {
  17. //改写物理返回键的逻辑
  18. if(keyCode==KeyEvent.KEYCODE_BACK) {
  19. if(mWebView.canGoBack()) {
  20. mWebView.goBack();//返回上一页面
  21. return true;
  22. } else {
  23. System.exit(0);//退出程序
  24. }
  25. }
  26. return super.onKeyDown(keyCode, event);
  27. }
  28. }

在未重写onKeyDown前的效果图:点击回退按钮,整个Activity就销毁了

重写onKeyDown后的效果图:

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

2、滚动事件监听

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

  1. public class MyWebView extends WebView {
  2. private OnScrollChangedCallback mOnScrollChangedCallback;
  3. public MyWebView(Context context) {
  4. super(context);
  5. }
  6. public MyWebView(Context context, AttributeSet attrs) {
  7. super(context, attrs);
  8. }
  9. public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
  10. super(context, attrs, defStyleAttr);
  11. }
  12. @Override
  13. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  14. super.onScrollChanged(l, t, oldl, oldt);
  15. if (mOnScrollChangedCallback != null) {
  16. mOnScrollChangedCallback.onScroll(l,t,oldl,oldt);
  17. }
  18. }
  19. public OnScrollChangedCallback getOnScrollChangedCallback() {
  20. return mOnScrollChangedCallback;
  21. }
  22. public void setOnScrollChangedCallback(
  23. final OnScrollChangedCallback onScrollChangedCallback) {
  24. mOnScrollChangedCallback = onScrollChangedCallback;
  25. }
  26. public static interface OnScrollChangedCallback {
  27. public void onScroll(int left,int top ,int oldLeft,int oldTop);
  28. }
  29. }

这段代码难度不大,就不再细讲了。

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

如果不想在 webview 中显示网页,而是直接跳转到浏览器的话,可以像下边那样调用。

  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发表  [回复]
  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网站的观点或立场
 
 
 
 
    个人资料
 
 
    • 访问:3855788次
    • 积分:24247
    • 等级: 
    • 排名:第256名
    • 原创:231篇
    • 转载:35篇
    • 译文:0篇
    • 评论:2581条
    我的新浪微博
    交流群来啦

新建了一个交流群,大家可以加入

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

博主需要你!!!

我的微信公众号

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

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

    博客专栏
《Animation动画详解》

文章:13篇

阅读:236559

    文章分类
    文章存档
    最新评论
 
 
公司简介|招贤纳士|广告服务|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈
网站客服杂志客服微博客服webmaster@csdn.net400-660-0108|北京创新乐知信息技术有限公司 版权所有|江苏知之为计算机有限公司|江苏乐知网络技术有限公司
京 ICP 证 09002463 号|Copyright © 1999-2017, CSDN.NET, All Rights Reserved 
 

WebView使用详解(二)——WebViewClient与常用事件监听的更多相关文章

  1. Android WebView 开发详解(二)

    转载请注明出处  http://blog.csdn.net/typename/article/details/39495409 powered by miechal zhao   概览: Androi ...

  2. 详解 RAC 中各种IP和监听的意义

    一.SCAN 概念 SCAN(Single Client Access Name)是 Oracle从11g R2开始推出的,客户端可以通过 SCAN 特性负载均衡地连接到 RAC数据库 SCAN 最明 ...

  3. taro 填坑之路(二)taro 通过事件监听 实现组件间传值

    1.组件传值的方式 2.事件监听原理 3.事件管理器 utils/event.js /** * 事件池(事件管理器) * 通过事件监听传值 */ class Event { constructor() ...

  4. Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)

    View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇  ...

  5. PopUpWindow使用详解(二)——进阶及答疑

      相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  6. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  7. logback -- 配置详解 -- 二 -- <appender>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  8. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  9. HTTPS详解二:SSL / TLS 工作原理和详细握手过程

    HTTPS 详解一:附带最精美详尽的 HTTPS 原理图 HTTPS详解二:SSL / TLS 工作原理和详细握手过程 在上篇文章HTTPS详解一中,我已经为大家介绍了 HTTPS 的详细原理和通信流 ...

随机推荐

  1. MongoDB - 运行

    运行 mongod --dbpath (mongod is the "Mongo Daemon") 在shell用mongo或者用studio 3t可视化连接 创建用户 db.cr ...

  2. windows10 通过ssh访问 linux

    安装openssh服务 Win10其实自带OpenSSH 没有的话,点击上面的添加找到并安装 在服务里设置对应服务开机启动 添加服务器到已知主机 ssh-keygen -R 你的服务器ip 连接Lin ...

  3. 吴裕雄--天生自然Numpy库学习笔记:NumPy 数学函数

    NumPy 包含大量的各种数学运算的函数,包括三角函数,算术运算的函数,复数处理函数等. NumPy 提供了标准的三角函数:sin().cos().tan(). import numpy as np ...

  4. Passive Client Feature

    Q. How is the passive client feature used on Wireless LAN Controllers? A. Passive clients are wirele ...

  5. 前端开发中的 MVC、MVP、MVVM 模式

    MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...

  6. 反射实现定位Servlet中的方法

    public class BaseServlet extends HttpServlet{ @Override protected void service(HttpServletRequest re ...

  7. css不起作用报错:Resource interpreted as Stylesheet but transferred with MIME type text/html

    解决:https://blog.csdn.net/sky_cui/article/details/86703706 找了好久........

  8. cmd命令下载maven管理需要的依赖jar包

    首先在maven官网https://mvnrepository.com/  搜索你需要的jar包,找到下面的下载链接,在修改命令,然后cmd下载. cmd命令下载Maven需要jar包 cmd输入下面 ...

  9. TimeSeriesEditor时间序列编辑软件之实战ReoGrid表格控件和Zedgraph绘图控件

    最近用ReoGrid表格控件和Zedgraph绘图控件写了一个TimeSeriesEditor时间序列编辑软件,如下图. 目的就是体验一下这两个空间的用法,感觉还是挺好用的, 关于软件的使用说明可以访 ...

  10. springboot devtool热部署的一个大坑

    spring.devtools.restart.poll-interval=3000ms spring.devtools.restart.quiet-period=2999ms 别问我为什么,问就是一 ...