关闭

启舰

当乌龟有了梦想……

 
 
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. 2020年python学习进阶方向

     相信很多友人在学习python过程都会遇到很多 虽然python入门很容易  但是难免会遇到瓶颈 遇到问题没人交流 很难提升   对此 给你们简单指点学习方向  1.认识python linux基本 ...

  2. 第三方控件引起的"类型Universe无法解析程序集"的血案

    前一阵子在项目中添加了IrisSkin2皮肤控件,今天用VS打开悲剧了. 提示"类型Universe无法解析程序集:System.Design,Version=2.0.0.0,Culture ...

  3. UIViewController的API

    - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil; 返回一个新初始化 ...

  4. 安洵杯iamthinking(tp6反序列化链)

    安洵杯iamthinking tp6pop链 考点: 1.tp6.0反序列化链 2.parse_url()绕过 利用链: 前半部分利用链(tp6.0) think\Model --> __des ...

  5. 201771010135杨蓉庆 《面对对象程序设计(java)》第九周学习总结

    第7章 异常.日志.断言和调试 1.实验目的与要求 (1) 掌握java异常处理技术: (2) 了解断言的用法: (3) 了解日志的用途: (4) 掌握程序基础调试技巧: 一.理论知识 1.异常:在程 ...

  6. plus接口

    //获取手机端本地文件路径 plus.io.resolveLocalFileSystemURL(url, success(e){ }, fail(e){ })

  7. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用激活函数

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  8. spring boot 配置时区差别

    前提 数据库时区:GMT+8 show variables like '%time_zone%'; 本机电脑时区: 情景一.不指定时区 传递的参数映射到Data不指定时区,连接数据库不指定时区,保存时 ...

  9. 一大波新款iPhone跟安卓厂商抢夺5G市场

    据外媒最新报道称,苹果已经基本完成了今年iPhone的推新阵容,其发布的多款新机中,将涵盖399美元-1149美元的售价区间,特别是5G手机,起步价可能会很亲民,其目的在于进一步占据市场. 今年苹果将 ...

  10. GCC 升级

    1.下载源码 wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.5/gcc-4.8.5.tar.gz 2.下载依赖包编译安装 GCC 需要依赖 mpc,mpfr,gmp包. ...