android webview一篇文章全面瞭解(基本使用,url攔截,js跟java互動)
1.前言
最近幾年混合應用越來越流行,及一部分功能用原生程式碼開發,一部分功能用html5實現。那什麼時候用原生什麼時候用網頁呢?很多人第一反應就是經常變化的頁面用網頁開發,避免經常發包,不全對。其實因為網頁使用體驗遠遠不及原生開發,所以一般有以下兩種情況建議使用網頁代替原生:
1.試水功能
2.類似雙11主會場,這類只在固定時間內使用的功能。
2.基本使用方法
1)xml佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title_name"
android:layout_width="match_parent"
android:layout_height="44dp"
android:gravity="center"
android:background="#987654"
android:text="title"/>
<ProgressBar
android:id="@+id/webview_progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="2dp" />
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>
</LinearLayout>
2)利用WebSettings設定一些頁面屬性,比如,頁面字型的大小,是否支援js,支援縮小放大,支援本地儲存,支援快取等。
public static void initWebSettings( WebView webView) {
WebSettings webSettings = webView.getSettings();
webSettings.setDefaultTextEncodingName("UTF-8");//設定預設為utf-8
webSettings.setTextZoom(100);//設定WebView中載入頁面字型變焦百分比,預設100
//屬性可以讓webview只顯示一列,也就是自適應頁面大小,不能左右滑動
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
} else {
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
}
//設定此屬性,可任意比例縮放
webSettings.setUseWideViewPort(false);
webSettings.setLoadWithOverviewMode(true);
//頁面支援縮放
webSettings.setBuiltInZoomControls(false);
webSettings.setSupportZoom(false);
webSettings.setDisplayZoomControls(false);
//設定支援js
webSettings.setJavaScriptEnabled(true);
webSettings.setSavePassword(false);
//設定 快取模式
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
// 開啟 DOM storage API 功能
webSettings.setDomStorageEnabled(true);
webView.setVerticalScrollBarEnabled(false);
webView.setVerticalScrollbarOverlay(false);
webView.setHorizontalScrollBarEnabled(false);
webView.setHorizontalScrollbarOverlay(false);
}
3)載入內容
(1)載入assets目錄下的本地網頁
一般我們都是把html檔案放在assets目錄下, WebView呼叫assets目錄下的本地網頁和圖片等資源非常方便,如下程式碼所示:
webView.loadUrl("file:///android_asset/html/intermodulation.html");
(2)載入遠端網頁
webView.loadUrl("http://www.baidu.com/");
(3)使用 LoadData 或者 loadDataWithBaseURL方法載入內容
有時候我們的webview可能只是html片段,而不是一個完整的網頁,事實上絕大多數時候都是如此,完整的網頁無需做成應用,而直接在瀏覽器訪問。這種情況我們使用 LoadData 或者 loadDataWithBaseURL方法,後者用的最多:
void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)
loadDataWithBaseURL()比loadData()多兩個引數,可以指定HTML程式碼片段中相關資源的相對根路徑,也可以指定歷史Url,其餘三個引數相同。
這裡主要注意引數baseUrl,baseUrl指定了你的data引數中資料是以什麼地址為基準的,因為data中的資料可能會有超連結或者是image元素,而很多網站的地址都是用的相對路徑,如果沒有baseUrl,webview將訪問不到這些資源。如下所示:
String body ="示例:這裡有個img標籤,地址是相對路徑<img src='/uploads/allimg/130923/1FP02V7-0.png' />";
mWebView.loadDataWithBaseURL("http://baidu.com", body, "text/html", "utf-8",null);
如果baseUrl沒有指定為http://baidu.com,那麼這張圖片將顯示不出來。
到這裡,基本的webview功能已經可以使用了。
3.android應用中攔截js點選跳轉,替換成跳轉到原生介面。
實際專案中,可能會顯示網頁標題,需要展示載入進度,或者當點選網頁中一個按鈕或者一個商品,需要跳轉到原生介面,這個時候就需要用到兩個方法:
WebViewClient主要用來攔截網頁中的請求,開始,結束請求等操作。
webView.setWebViewClient(new WebViewClient() {
//返回值:true 不會顯示網頁資源,需要等待你的處理,false 就認為系統沒有做處理,會顯示網頁資源
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//當url裡面包含webview欄位的時候,則跳轉到ShowActivity原生頁面,否則還是繼續顯示網頁
//比如:在百度輸入框裡面輸入webview在點選搜尋,再點選任何有webview欄位的連結,
//則不繼續顯示網頁,而是跳轉到自己定義的原生頁面
if (!TextUtils.isEmpty(url)
&& url.contains("webview")) {
Intent intent = new Intent(ClickInterceptionActivity.this, ShowActivity.class);
intent.putExtra("url", url);
startActivity(intent);
return true;
}
return false;
}
//在頁面開始載入時候做一些操作,比如展示進度條
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
webview_progressbar.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
//在頁面載入完成的時候做一些操作,比如隱藏進度條
@Override
public void onPageFinished(WebView view, String url) {
webview_progressbar.setVisibility(View.GONE);
super.onPageFinished(view, url);
}
});
WebChromeClient主要輔助WebView處理JavaScript的對話方塊、網站圖示、網站title、載入進度等。
webView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
webview_progressbar.setProgress(newProgress);
super.onProgressChanged(view, newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
title_name.setText(title);
super.onReceivedTitle(view, title);
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
}
});
效果如下所示:帶有載入進度和標題
當在輸入框中webview,並點選【百度一下】,正常情況會進入搜尋結果網頁,由於我們重寫了shouldOverrideUrlLoading方法,對url實現了攔截,則跳轉到原生頁面。
4.js和Java的互動
除了上面的簡單展示,很多專案中還會有js跟java的雙向互動。
1)js呼叫android原生方法
1.addJavascriptInterface
webView.addJavascriptInterface(new clickOnJS(), "click");
2.在android中定義待呼叫方法:
class clickOnJS {
@JavascriptInterface
public void OnClick() {
Toast.makeText(IntermodulationActivity.this, "呼叫java成功", Toast.LENGTH_SHORT).show();
}
}
3.js定義方法去呼叫java方法。
$(function(){
$('.payment').click(function(){
window.click.OnClick();
});
});
效果如下圖所示:點選【js呼叫java】按鈕,則彈出toast,證明成功呼叫java原生方法。
2)android呼叫js方法
當點選android頁面上某個按鈕的時候,改變js頁面的內容,其實就是android原生給js傳值。
1.點選標題,則呼叫js方法
title_name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//呼叫js方法
webView.loadUrl("javascript:setcontent(2)");
}
});
2.js程式碼實現,修改cr的值
function setcontent(content){
$('.num ,.cr').text(content);
}
效果如下圖所示:點選標題,則呼叫js的setcontent方法,【待修改點】變成【2】,則證明成功呼叫java原生方法。
5.部分原始碼
1)攔截js點選跳轉關鍵程式碼類:
public class ClickInterceptionActivity extends Activity {
private TextView title_name;
private ProgressBar webview_progressbar;
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_click_interception);
initView();
initWebViewSettings();
}
/**
* 初始化佈局元件
*/
private void initView() {
title_name = (TextView) findViewById(R.id.title_name);
webview_progressbar = (ProgressBar) findViewById(R.id.webview_progressbar);
webView = (WebView) findViewById(R.id.webview);
}
/**
* 初始化webview配置
*/
private void initWebViewSettings() {
WebViewSettings.initWebSettings(webView);
webView.setWebViewClient(new WebViewClient() {
//返回值:true 不會顯示網頁資源,需要等待你的處理,false 就認為系統沒有做處理,會顯示網頁資源
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//當url裡面包含webview欄位的時候,則跳轉到ShowActivity原生頁面,否則還是繼續顯示網頁
//比如:在百度輸入框裡面輸入webview在點選搜尋,再點選任何有webview欄位的連結,
//則不繼續顯示網頁,而是跳轉到自己定義的原生頁面
if (!TextUtils.isEmpty(url)
&& url.contains("webview")) {
Intent intent = new Intent(ClickInterceptionActivity.this, ShowActivity.class);
intent.putExtra("url", url);
startActivity(intent);
finish();
return true;
}
return false;
}
//在頁面開始載入時候做一些操作,比如展示進度條
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
webview_progressbar.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
//在頁面載入完成的時候做一些操作,比如隱藏進度條
@Override
public void onPageFinished(WebView view, String url) {
webview_progressbar.setVisibility(View.GONE);
super.onPageFinished(view, url);
}
});
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
webview_progressbar.setProgress(newProgress);
super.onProgressChanged(view, newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
title_name.setText(title);
super.onReceivedTitle(view, title);
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
}
});
webView.loadUrl("http://www.baidu.com/");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
2)js跟java互動關鍵類:
public class IntermodulationActivity extends Activity {
private TextView title_name;
private ProgressBar webview_progressbar;
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intermodulation);
initView();
initWebViewSettings();
}
/**
* 初始化佈局元件
*/
private void initView() {
title_name = (TextView) findViewById(R.id.title_name);
webview_progressbar = (ProgressBar) findViewById(R.id.webview_progressbar);
webView = (WebView) findViewById(R.id.webview);
title_name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//呼叫js方法
webView.loadUrl("javascript:setcontent(2)");
}
});
}
/**
* 初始化webview配置
*/
private void initWebViewSettings() {
WebViewSettings.initWebSettings(webView);
webView.addJavascriptInterface(new clickOnJS(), "click");
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!TextUtils.isEmpty(url)
&& url.contains("webview")) {
Intent intent = new Intent(IntermodulationActivity.this, ShowActivity.class);
intent.putExtra("url", url);
startActivity(intent);
}
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
webview_progressbar.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webview_progressbar.setVisibility(View.GONE);
}
});
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
webview_progressbar.setProgress(newProgress);
super.onProgressChanged(view, newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
title_name.setText(title);
super.onReceivedTitle(view, title);
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
}
});
webView.loadUrl("file:///android_asset/html/intermodulation.html");
}
class clickOnJS {
@JavascriptInterface
public void OnClick() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Toast.makeText(IntermodulationActivity.this, "呼叫java成功", Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
3)js實現類:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;"
name="viewport"/>
<title>js和java互動(點選,點選)</title>
<link href="images/styles.css" rel="stylesheet" type="text/css">
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body class="mbg1">
<div class="paybox pay2box">java修改js============== <span class="cr">待修改點</span></div>
<span class="payment"><a href="#">js呼叫java</a></span>
<script>
$(function(){
$('.payment').click(function(){
window.click.OnClick();
});
});
function setcontent(content){
$('.num ,.cr').text(content);
}
</script>
</body>
</html>
6.demo下載地址: