WebView 详解
基本用法
- 加载网页
//加载网页链接 mWebView.loadUrl("http://www.itheima.com"); //加载本地assets目录下的网页 mWebView.loadUrl("file:///android_asset/demo.html");
- 加载控制
webView.reload(); //刷新页面(当前页面的所有资源都会重新加载) webView.stopLoading(); //停止加载
- 控件高度距离
//获取当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。 webView.getScrollY(); //获取WebView控件的高度。 webView.getHeight();webView.getBottom(); //获取HTML的高度(原始高度,不包括缩放后的高度) webView.getContentHeight();
- WebView加载上一页和下一页
mWebView.goBack();//跳到上个页面 mWebView.goForward();//跳到下个页面 mWebView.canGoBack();//是否可以跳到上一页(如果返回false,说明已经是第一页) mWebView.canGoForward();//是否可以跳到下一页(如果返回false,说明已经是最后一页)
- WebView基本设置
WebSettings settings = mWebView.getSettings(); settings.setBuiltInZoomControls(true);// 显示缩放按钮(wap网页不支持) settings.setUseWideViewPort(true);// 支持双击缩放(wap网页不支持) settings.setJavaScriptEnabled(true);// 支持js功能
生命周期
@Override
protected void onResume() {
super.onResume();
//恢复webview的状态(不靠谱)
webView.resumeTimers();
//激活webView的状态,能正常加载网页
webView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//当页面被失去焦点被切换到后台不可见状态,需要执行onPause
//通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
webView.onPause();
//当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
//它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。(不靠谱)
webView.pauseTimers();
}
//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
//但是注意:webview调用destory时,webview仍绑定在Activity上
//这是由于自定义webview构建时传入了该Activity的context对象
//因此需要先从父容器中移除webview,然后再销毁webview:
ViewGroup parent = findViewById(R.id.container);
parent.removeView(webView);
webView.destroy();
WebViewClient 与 WebChromeClient
WebViewClient
mWebView.setWebViewClient(new WebViewClient() { // 开始加载网页 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); System.out.println("开始加载网页了"); } // 网页加载结束 @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); System.out.println("网页加载结束"); } // 所有链接跳转会走此方法 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { System.out.println("跳转链接:" + url); view.loadUrl(url);// 在跳转链接时强制在当前webview中加载 //此方法还有其他应用场景, 比如写一个超链接<a href="tel:110">联系我们</a>, 当点击该超链接时,可以在此方法中获取链接地址tel:110, 解析该地址,获取电话号码, 然后跳转到本地打电话页面, 而不是加载网页, 从而实现了webView和本地代码的交互 return true; } });
onPageStarted()onPageFinished():页面加载时和页面加载完毕时调用。
shouldOverrideKeyEvent():重写此方法才能处理浏览器中的按键事件。
shouldInterceptRequest():页面每一次请求资源之前都会调用这个方法(非UI线程调用)。
onLoadResource():页面加载资源时调用,每加载一个资源(比如图片)就调用一次。
onReceivedError():加载页面的服务器出现错误(比如404)时回调。
onReceivedSslError():重写此方法可以让webview处理https请求。
doUpdateVisitedHistory():更新历史记录。
onFormResubmission():应用程序重新请求网页数据。
onReceivedHttpAuthRequest():获取返回信息授权请求。
onScaleChanged():WebView发生缩放改变时调用。
onUnhandledKeyEvent():Key事件未被加载时调用。WebChromeClient
辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等
mWebView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); // 进度发生变化 System.out.println("进度:" + newProgress); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); // 网页标题 System.out.println("网页标题:" + title); } });
onReceivedTitle():获得网页的标题时回调。
onReceivedIcon():获得网页的图标时回调。
onCreateWindow():打开新窗口时回调。
onCloseWindow():关闭窗口时回调。
高级用法
缓存
- 缓存设置
WebSettings settings = mWebView.getSettings();
//只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//只加载缓存
settings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
//根据cache-control决定是否从网络上取数据
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
//不加载缓存
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
- 缓存清楚
//最简便的方式:
mWebView.clearCache(true);
//另外一种方式:
//删除缓存文件夹
File file = CacheManager.getCacheFileBaseDir();
if (file != null && file.exists() && file.isDirectory()) {
for (File item : file.listFiles()) {
item.delete();
}
file.delete();
}
//删除缓存数据库
context.deleteDatabase("webview.db");
context.deleteDatabase("webviewCache.db");
//清除当前webview访问的历史记录
//只会webview访问历史记录里的所有记录除了当前访问记录
Webview.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
Webview.clearFormData();
Cookie
- Cookie设置
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
String cookie = "name=xxx;age=18";
cookieManager.setCookie(URL, cookie);
CookieSyncManager.getInstance().sync();
获取Cookie
CookieManager cookieManager = CookieManager.getInstance(); String cookie = cookieManager.getCookie(URL);
清除Cookie
CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); //这个两个在 API level 21 被抛弃 cookieManager.removeSessionCookie(); cookieManager.removeAllCookie(); //Api 21 新增 //移除所有过期 cookie cookieManager.removeSessionCookies(); //移除所有的 cookie cookieManager.removeAllCookies(); //回调 CookieManager.getInstance().removeAllCookies(new ValueCallback<Boolean>() { @Override public void onReceiveValue(Boolean value) { // 清除结果 } });
CookieSyncManager.getInstance().sync();
#### 高级设置
```java
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局
//缩放操作
webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
webSettings.setTextZoom(2);//设置文本的缩放倍数,默认为 100
webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); //提高渲染的优先级
webSettings.setStandardFontFamily("");//设置 WebView 的字体,默认字体为 "sans-serif"
webSettings.setDefaultFontSize(20);//设置 WebView 字体的大小,默认大小为 16
webSettings.setMinimumFontSize(12);//设置 WebView 支持的最小字体大小,默认为 8
webSettings.setVerticalScrollBarEnabled(false); //vertical bar 不显示
webSettings.setHorizontalScrollBarEnabled(false); // horizontal bar 不显示
// 5.1以上默认禁止了https和http混用,以下方式是开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
//其他
webSettings.setAllowFileAccess(true); //设置可以访问文件
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
webSettings.setGeolocationEnabled(true);//允许网页执行定位操作
//分段加载HTML文件
if (VERSION.SDK_INT >= 21) {
WebView.enableSlowWholeDocumentDraw();
}
JavaScript 和 Native 交互
DSBridge-Android
用于JavaScript and native applications 相互调用
依赖引用
dependencies { //compile 'com.github.wendux:DSBridge-Android:3.0-SNAPSHOT' //support the x5 browser core of Tencent //compile 'com.github.wendux:DSBridge-Android:x5-3.0-SNAPSHOT' }
JavaScript 调用原生
原生提供调用方法
public class JsApi{ //for synchronous invocation //【err】易错点: msg 这个参数必须是Object否则JavaScript会不识别方法 @JavascriptInterface public String testSyn(Object msg) { return msg + "[syn call]"; } //for asynchronous invocation @JavascriptInterface public void testAsyn(Object msg, CompletionHandler handler) { handler.complete(msg+" [ asyn call]"); } }
加入DWebView生效
import wendu.dsbridge.DWebView ... DWebView dwebView= (DWebView) findViewById(R.id.dwebview); dwebView.addJavascriptObject(new JsApi(), null);
JavaScript 项目demo js-call-native.html(需要配置科学上网)
//cdn //<script src="https://unpkg.com/dsbridge@3.1.3/dist/dsbridge.js"> </script> //npm //npm install dsbridge@3.1.3 var dsBridge=require("dsbridge") //Call synchronously var str=dsBridge.call("testSyn","testSyn"); //Call asynchronously dsBridge.call("testAsyn","testAsyn", function (v) { alert(v); }) //Register javascript API for Native dsBridge.register('addValue',function(l,r){ return l+r; })
常用的第三方库
cordova
Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。
mui
- mui是最接近原生App体验的前端框架
参考博文