開發(fā)中使用WebView加載url瞭亮、html標(biāo)簽必不可少仙蚜,比如廣告委粉、活動(dòng)界面通過(guò)WebView加載具有實(shí)效性。下面介紹WebView使用方法栗涂。
webView.loadUrl(url);
loadUrl(url)這樣可以直接加載網(wǎng)頁(yè),但此時(shí)是通過(guò)手機(jī)瀏覽器打開的網(wǎng)頁(yè)忿墅,如果要使用WebView直接打開則需設(shè)置WebViewClient疚脐。
webView.setWebViewClient(new WebViewClient());
有關(guān)WebViewClient下面再詳細(xì)介紹亿柑。
對(duì)于加載Url注意如下:
1、如果是在線網(wǎng)址記得添加網(wǎng)絡(luò)訪問(wèn)權(quán)限
2式矫、在線網(wǎng)址中,如果要使用webview打開故慈,記得設(shè)置WebViewClient
3框全、打開本地html文件時(shí),是不需要設(shè)置WebViewClient拆撼,對(duì)應(yīng)的asstes目錄的url 為:file:///android_asset/xxxxx*
我們先來(lái)看如何根據(jù)需求設(shè)置webView屬性蚜印,可以調(diào)用WebView.getSettings()獲取設(shè)置WebView的WebSettings對(duì)象,通過(guò)WebSettings做屬性配置柒傻,各配置說(shuō)明如下:
WebSettings webSettings = webView.getSettings();
//設(shè)置開啟javascript支持
webSettings.setJavaScriptEnabled(true);
//設(shè)置支持縮放
webSettings.setSupportZoom(true);
//開啟縮放工具(會(huì)出現(xiàn)放大縮小的按鈕)
webSettings.setBuiltInZoomControls(true);
//WebView兩種緩存(網(wǎng)頁(yè)预侯、H5)方式,此處網(wǎng)頁(yè)不緩存
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
//允許JS打開新窗口(默認(rèn)false)
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
//打開本地緩存供JS調(diào)用
webSettings.setDomStorageEnabled(true);
//H5緩存內(nèi)存大忻臃肌(已過(guò)時(shí)魄衅,不必設(shè)置已可自動(dòng)管理)
//webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//H5緩存路徑
String absolutePath = getApplicationContext().getCacheDir().getAbsolutePath();
//H5緩存大小
webSettings.setAppCachePath(absolutePath);
//是否允許WebView訪問(wèn)內(nèi)部文件(默認(rèn)true)
webSettings.setAllowFileAccess(true);
//支持存儲(chǔ)H5緩存
webSettings.setAppCacheEnabled(true);
//啟動(dòng)概述模式瀏覽界面哲银,當(dāng)頁(yè)面寬度超過(guò)WebView顯示寬度時(shí),縮小頁(yè)面適應(yīng)WebView(默認(rèn)false)
webSettings.setLoadWithOverviewMode(true);
//支持手勢(shì)縮放(如webView中需要手動(dòng)輸入用戶名盲泛、密碼等郁竟,則webview必須設(shè)置支持獲取手勢(shì)焦點(diǎn))
webView.requestFocusFromTouch();
// 清除緩存
webView.clearCache(true);
// 清除緩存防止登錄上次的賬號(hào)
CookieManager.getInstance().removeAllCookie();
Java調(diào)用JavaScript
java調(diào)用JavaScript中的函數(shù)很簡(jiǎn)單讥蟆,只需要執(zhí)行如下代碼即可:
webView.loadUrl("javascript:toast()");
toast()是JS中方法。
JavaScript調(diào)用Java
三個(gè)步驟:
1.調(diào)用WebSettings的setJavaScriptEnabled方法使支持JavaScript調(diào)用玻靡。
2.調(diào)用WebView的addJavascriptInterface方法將應(yīng)用中的Java對(duì)象暴露給JavaScript邻寿;
3.在JavaScript腳本中調(diào)用步驟二暴露出來(lái)的Java對(duì)象的方法。
在webView.addJavascriptInterface(new JsBradge(), "android");實(shí)現(xiàn)醋拧;其中JsBradge()中是申明了JS可調(diào)用的本地方法,“android”是與JS協(xié)商的對(duì)象名稱,JS端可通過(guò)android.toastMessage(" ")調(diào)用Java方法沐序。
注:如下需加上@JavascriptInterface注解,避免引起WebView遠(yuǎn)程代碼執(zhí)行漏洞邑时。
public class JsBradge {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}
WebViewClient
WebViewClient可以拿到WebView在訪問(wèn)網(wǎng)絡(luò)各個(gè)階段的回調(diào)晶丘,包括加載前后,失敗等(以下注釋來(lái)源"啟艦"博客)
/**
* 在開始加載網(wǎng)頁(yè)時(shí)會(huì)回調(diào)
*/
public void onPageStarted(WebView view, String url, Bitmap favicon)
/**
* 在結(jié)束加載網(wǎng)頁(yè)時(shí)會(huì)回調(diào)
*/
public void onPageFinished(WebView view, String url)
/**
* 攔截 url 跳轉(zhuǎn),在里邊添加點(diǎn)擊鏈接跳轉(zhuǎn)或者操作
*/
public boolean shouldOverrideUrlLoading(WebView view, String url)
/**
* 加載錯(cuò)誤的時(shí)候會(huì)回調(diào)郁油,在其中可做錯(cuò)誤處理蚕苇,比如再請(qǐng)求加載一次,或者提示404的錯(cuò)誤頁(yè)面
*/
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)
/**
* 當(dāng)接收到https錯(cuò)誤時(shí),會(huì)回調(diào)此函數(shù),在其中可以做錯(cuò)誤處理
*/
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
/**
* 在每一次請(qǐng)求資源時(shí)罗心,都會(huì)通過(guò)這個(gè)函數(shù)來(lái)回調(diào)
*/
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return null;
}
以上可以根據(jù)需求做相應(yīng)處理里伯,其中shouldOverrideUrlLoading方法會(huì)在加載超鏈接時(shí)回調(diào)過(guò)來(lái),當(dāng)需要WAP與原生互調(diào)等劫持URL時(shí)用到,重寫該方法然后return true即可削祈,當(dāng)不需要劫持在else中重新loadUrl(url)即可。
// 當(dāng)點(diǎn)擊鏈接時(shí),希望覆蓋而不是打開新窗口
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// showProgressDlg();
// 攔截?fù)屬?gòu)商品削饵,跳回APP搶購(gòu)商品詳情
if (url.contains("proId") && url.contains("qgDetail.html")) {
String actid = url.split("\\?")[1].split("&")[0].split("=")[1];
ActivityController.startActProductDetailActivity(WebActivity.this, actid, "");
} else if (url.contains("goodDetail.html") && url.contains("proId")) {
String id = url.split("\\?")[1].split("&")[0].split("=")[1];
ActivityController.startGoodsDetailActivity(WebActivity.this, id);
} else {
view.loadUrl(url);
}
return true;
}
WebChromeClient
可以在其中加載進(jìn)度條,獲取鏈接的標(biāo)題等方法刹碾。
/**
* 當(dāng)網(wǎng)頁(yè)調(diào)用alert()來(lái)彈出alert彈出框前回調(diào)迷帜,用以攔截alert()函數(shù)
*/
public boolean onJsAlert(WebView view, String url, String message,JsResult result)
/**
* 當(dāng)網(wǎng)頁(yè)調(diào)用confirm()來(lái)彈出confirm彈出框前回調(diào)物舒,用以攔截confirm()函數(shù)
*/
public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
/**
* 當(dāng)網(wǎng)頁(yè)調(diào)用prompt()來(lái)彈出prompt彈出框前回調(diào),用以攔截prompt()函數(shù)
*/
public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result)
/**
* 打印 console 信息
*/
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
/**
* 通知程序當(dāng)前頁(yè)面加載進(jìn)度
*/
public void onProgressChanged(WebView view, int newProgress)
下面附上我項(xiàng)目里的一段代碼,加載進(jìn)度條跟獲取Title:
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
progressBar.setVisibility(View.GONE);
} else {
if (progressBar.getVisibility() == View.GONE)
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(newProgress);
}
}
@Override
public void onReceivedTitle(WebView view, String title) {
setActivityTitle(title);
}
webView加載html
當(dāng)后臺(tái)返回不是url而是一連串的html標(biāo)簽時(shí),可以通過(guò)
webView.loadDataWithBaseURL(null, html , "text/html", "UTF-8", "");
之前可以設(shè)置:
//水平不顯示滾動(dòng)條
webView.setHorizontalScrollBarEnabled(false);
//垂直不顯示滾動(dòng)條
webView.setVerticalScrollBarEnabled(false);
//初始化壓縮比例
webView.setInitialScale(50);
// webview自適應(yīng)屏幕尺寸
webView.getSettings().setSupportZoom(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
//設(shè)置圖片顯示方式
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
// 設(shè)置背景色
//webView.setBackgroundColor(0);
webView.getSettings().setDefaultTextEncodingName("UTF-8");
//設(shè)置圖片最大尺寸,高度自適應(yīng)堰怨;文字顏色、字體大小饿肺、行高嵌牺、首行縮進(jìn)兩個(gè)字符
// 包含去除img style 的js代碼
String head = "<html><head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> <meta name " +
"=\"viewport\" content =\"width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1," +
" user-scalable=no\"/><style type=\"text/css\">" +
"p {font-size:14px;line-height:20px;color:#303030;text-indent:2em;} " +
"img{max-width:100% ;height:auto !important;} a {color:#3E62A6;}\\u007Fpre {font-size:9pt;line-height:12pt;font-family:Courier New,Arial;border:1px solid #ddd;border-left:5px solid #6CE26C;background:#f6f6f6;padding:5px;}</style></head>"
+ "<script type=\"text/javascript\"charset=\"utf-8\">window.onload=function(){var imgArr=document.getElementsByTagName(\"img\");for(var i in imgArr){imgArr[i].removeAttribute(\"style\")}}</script>";
html = head + "<body>" + html + "<script type=\"text/javascript\"charset=\"utf-8\">var imgArr=document.getElementsByTagName(\"img\");for(var i in imgArr){imgArr[i].removeAttribute(\"style\");</script>"
+ "</body></html>";
回退事件處理
當(dāng)回退時(shí),若不監(jiān)聽回退鍵點(diǎn)擊返回時(shí)不會(huì)回退到上一web界面爸舒,而是直接結(jié)束當(dāng)前Activity蟋字,通過(guò)canGoBack判斷是否可回退,goBack進(jìn)行回退扭勉。代碼如下:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
if (webView.copyBackForwardList().getItemAtIndex(webView.copyBackForwardList().getSize() - 1).getUrl().contains("activity/201412/act_common.html")) {
//解決活動(dòng)重定向無(wú)法回退到原生界面
return super.onKeyDown(keyCode, event);
} else {
webView.goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
以上你看到copyBackForwardList方法鹊奖,這個(gè)是為了解決重定向可以正確退出當(dāng)前Activity而設(shè)置。
先說(shuō)下問(wèn)題涂炎,當(dāng)你loadUrl(url1)時(shí)忠聚,web端將url1更換成了url2,所以顯示出來(lái)的是url2界面唱捣。webview中copyBackForwardList是專門用來(lái)管理url棧的两蟀,但此時(shí),不光url2入棧震缭,url1也入棧了赂毯,所以當(dāng)在url2界面時(shí),canGoBack返回的也是true拣宰,當(dāng)按回退鍵時(shí)就會(huì)回到url1(不會(huì)顯示)然后馬上又回到url2界面党涕,這就是按回退無(wú)法finish當(dāng)前Activity而陷入重新加載url2界面的原因和解決辦法。
注意在擁有WebVie的Activity中需要在onDestory方法中銷毀webView以防內(nèi)存泄漏巡社,代碼如下:
@Override
protected void onDestroy() {
//銷毀webview膛堤,避免內(nèi)在泄漏
if (webView != null) {
//移除webView確保Detach
ViewGroup parent = (ViewGroup) webView.getParent();
if (parent != null) {
parent.removeView(webView);
}
webView.removeAllViews();
webView.clearHistory();
webView.destroy();
webView = null;
}
super.onDestroy();
}
參考:
WebView使用詳解(二)——WebViewClient與常用事件監(jiān)聽
《Android高級(jí)進(jìn)階》——顧浩鑫/著