1. 使用 WebView 加載 HTML 四種方式
//方式1:直接加載服務器對應的 URL
webView.loadUrl("http://baidu.com");
//方式2:加載開發項目資源文件夾下的 HTML 文件
webView.loadUrl("file:///android_asset/test.html");
//方式3:加載手機 sdcard 上的 HTML 文件
webView.loadUrl("content://com.ansen.webview/sdcard/test.html");
//方式4 使用 WebView 直接解析並顯示 HTML 代碼
webView.loadDataWithBaseURL(null
,"<html>
<head>
<title> 歡迎 </title>
</head>" +
"<body><h2>你可以使用 WebView 解析 HTML 源碼</h2>
</body>
</html>"
, "text/html"
, "utf-8"
, null);
2. WebViewClient與WebChromeClient區別
WebViewClient主要幫助WebView處理各種通知、請求事件的,有以下常用方法:
- onPageFinished 頁面請求完成
- onPageStarted 頁面開始加載
- shouldOverrideUrlLoading 攔截url
- onReceivedError 訪問錯誤時回調,例如訪問網頁時報錯404,在這個方法回調的時候可以加載錯誤頁面。
WebChromeClient主要輔助WebView處理Javascript的對話框、網站圖標、網站title、加載進度等,有以下常用方法。
- onJsAlert webview不支持js的alert彈窗,需要自己監聽然後通過dialog彈窗
- onReceivedTitle 獲取網頁標題
- onReceivedIcon 獲取網頁icon
- onProgressChanged 加載進度回調
3. WebSettings 常用設置
webSettings.setJavaScriptEnabled //是否允許使用 JS
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//設置緩存方式,共有四種可選
- LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據
- LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。
- LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據.
- LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。
webSettings.setBuiltInZoomControls(false); // 是否使用內置縮放機制
webSettings.setDisplayZoomControls(true); // 是否顯示內置縮放控件
4. WebView 官方文檔介紹
https://developer.android.google.cn/reference/android/webkit/WebView
5. 使用 WebView 需要權限
<uses-permission android:name="android.permission.INTERNET" />
6. 參考文檔
https://www.jianshu.com/p/a6f7b391a0b8
https://blog.csdn.net/lowprofile_coding/article/details/77928614
7. WebView 示例代碼
MainActivity
package com.demo.thorn.webviewdemo; import android.graphics.Bitmap; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private WebView webView; private ProgressBar progressBar; private final static int KIND_1 = 1; private final static int KIND_2 = 2; private final static int KIND_3 = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progressBar= findViewById(R.id.progressbar);//進度條 webView =findViewById(R.id.webview); initWebView(KIND_1);//加載 asset 文件夾下 html //initWebView(KIND_2);//加載 url //initWebView(KIND_3);//使用 webview 示 html } private void initWebView(int loadKind) { initWebViewSettings(); webView.addJavascriptInterface(this,"android");//添加js監聽 這樣 html 就能調用客戶端 webView.setWebChromeClient(webChromeClient);//處理 JS 的彈窗操作 webView.setWebViewClient(webViewClient);//處理 JS 返回的結果 //選擇加載模式 switch (loadKind){ case KIND_1: webView.loadUrl("file:///android_asset/test.html"); break; case KIND_2: webView.loadUrl("http://www.baidu.com/"); break; case KIND_3: webView.loadDataWithBaseURL(null,"<html><head><title> Welcome </title></head>" + "<body><h2>This is Your Body</h2></body></html>", "text/html" , "utf-8", null); break; default: break; } } private void initWebViewSettings() { WebSettings webSettings= webView.getSettings(); webSettings.setJavaScriptEnabled(true);//允許使用js /** * LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據 * LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。 * LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據. * LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。 */ webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//不使用緩存,只從網絡獲取數據. //支持屏幕縮放 webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); //不顯示webview縮放按鈕 webSettings.setDisplayZoomControls(false); } //WebViewClient主要幫助WebView處理各種通知、請求事件 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) {//頁面開始加載 progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) {//頁面加載完成 progressBar.setVisibility(View.GONE); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.i("jin","攔截 url:"+url); if(url.equals("http://www.google.com/")){ Toast.makeText(MainActivity.this,"國內不能訪問google,攔截該 url ",Toast.LENGTH_LONG).show(); return true;//表示我已經處理過了 } return super.shouldOverrideUrlLoading(view, url); } }; //WebChromeClient 主要輔助 WebView 處理 Javascript 的對話框、網站圖標、網站 title 、加載進度等 private WebChromeClient webChromeClient=new WebChromeClient(){ //不支持js的alert彈窗,需要自己監聽然後通過dialog彈窗 @Override public boolean onJsAlert(WebView webView, String url, String message, JsResult result) { AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext()); localBuilder.setMessage(message).setPositiveButton("確定",null); localBuilder.setCancelable(false); localBuilder.create().show(); //注意: //必須要這一句代碼:result.confirm()表示: //處理結果爲確定狀態同時喚醒WebCore線程 //否則不能繼續點擊按鈕 result.confirm(); return true; } //獲取網頁標題 @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); Log.i("jin","網頁標題:"+title); } //加載進度回調 @Override public void onProgressChanged(WebView view, int newProgress) { progressBar.setProgress(newProgress); } }; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.i("jin","是否有上一個頁面:"+webView.canGoBack()); if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK){//點擊返回按鈕的時候判斷有沒有上一頁 webView.goBack(); // goBack()表示返回webView的上一頁面 return true; } return super.onKeyDown(keyCode,event); } /** * JS 調用 android 的方法 * @param str * @return */ @JavascriptInterface //仍然必不可少 public void getClient(String str){ Log.i("jin","客戶端接收到了數據:"+str); } @Override protected void onDestroy() { super.onDestroy(); //釋放資源 webView.destroy(); webView=null; } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.demo.thorn.webviewdemo.MainActivity"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/> <ProgressBar android:id="@+id/progressbar" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="3dip" android:max="100" android:progress="0" android:visibility="gone"/> </android.support.constraint.ConstraintLayout>
test.html (文件路徑:WebViewDemo\app\src\main\assets\test.html)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>這裏是標題! </title> <style type="text/css"> dd { margin-top:30px; /* 上外邊距30像素 */ } </style> </head> <body> <div id="wrap"> <div id="header"><h1>這裏是 Header </h1> </div> <div id="main"> <dl> <dd><a href="http://www.baidu.com">點擊跳轉到百度</a></dd> <dd><a href="http://www.google.com">點擊跳轉到google</a></dd> <dd> <button id='callback_client' onclick="callBackClient()" type="button">用 js 調用客戶端中的方法 </button> </dd> </dl> </div> </body> <script> function callBackClient(){ alert("調用客戶端的 getClient 方法,並傳遞了數據");//彈窗 javascript:android.getClient("WebView 中傳遞的數據");//調用客戶端的 getClient 方法,並傳遞了數據 } </script> </html>