WebView的基本使用及相關特性

weixin_34321977發表於2018-12-18

WebView 是一個顯示網頁內容的元件,可以顯示網路上的一些線上內容並且可以作為 Web 瀏覽器滾動顯示的內容,它使用 WebKit作為渲染引擎來顯示網頁,裡面包括放大、縮小、執行文字搜尋等進行前後導航的方法。

注意 :如果要在 WebView 中顯示線上網頁等內容時,需要在 AndroidManifest.xml 檔案中新增網路許可權,參考如下:

<uses-permission android:name="android.permission.INTERNET" />

基本用法

預設情況下 WebView 不啟用 JavaScript ,網頁錯誤也將被忽略,如果僅僅是在 UI 上顯示一段 HTML,這就會非常好, 使用者在不需要再閱讀之前與使用者互動,網頁不需要與使用者互動 ,如果你需要一個完整的瀏覽器,你需要呼叫相應的 Intent 去啟動瀏覽器去執行某些操作,而不是使用 WebView 來顯示,呼叫系統瀏覽器使用如下程式碼:

Uri uri = Uri.parse("https://www.example.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
 

使用 WebView 主要有兩種使用方式,在 Activity 等 onCreate() 方法直接建立使用或者在佈局檔案中引入,參考如下:

1. 在程式碼中直接建立 WebView

WebView webview = new WebView(this);
//這裡將整個 Activity 視窗作為 WebView 的顯示介面,也可單獨放在某個佈局中
setContentView(webview);


2. 在佈局檔案中使用 WebView

<WebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</WebView>

那麼,我們如何載入一個網頁呢,如果網頁是本地的又如何載入呢,還有如何載入一段 HTML 的片段呢,常用的載入方法主要有兩個,如下:

1. 載入一個完整的網頁

這裡測試使用百度首頁、CSDN首頁、騰訊首頁進行測試,測試百度首頁時,需要設定如下屬性網頁內容才能正確顯示,如果不設定將顯示為白屏:

webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webView.loadUrl("https://www.baidu.com");

測試 CSDN 首頁時,會提示開啟系統帶瀏覽器的應用去開啟該頁面,設定如下屬性才能直接載入網頁內容:

webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://blog.csdn.net");

測試騰訊首頁時可以直接載入首頁內容:

webView.loadUrl("http://www.qq.com");

測試環境可能不同,結果也不相同。

2. 載入本地的 HTML 檔案

其中載入 SD 卡上的 HTML 檔案時要申請訪問 SD 卡上的許可權 Manifest.permission.WRITE_EXTERNAL_STORAGE,參考如下:

//載入 assets 目錄下的 HTML 檔案
webView.loadUrl("file:///android_asset/mine.html");
//載入 SD 卡上的 HTML 檔案
webView.loadUrl("file:///"+Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+"mine.html");

3. 載入 HTML 片段

載入 HTML 片段時,要設定字符集,否則會出現亂碼,參考如下:

//載入 HTML 片段,設定字符集防止亂碼出現
webView.loadData(Util.getHtmlData(),"text/html; charset=UTF-8",null);

WebView 的設定與介面處理主要有以下幾個方面:

  1. 建立並設定 WebChromeClient,主要是輔助 WebView 來處理 JavaScript 的對話方塊、網站標題、載入進度等;
  2. 建立並設定 WebViewClient, 主要是提供各種事件的回撥等;
  3. 通過 WebSetting 物件可以設定 WebView 的各種相關屬性,如支援 JavaScript 、設定 WebView 快取、字型大小等;
  4. JS 與 Java 的互相呼叫,如使用addJavascriptInterface(Object,String)方法將Java物件注入WebView。此方法允許您將Java物件注入到頁面的JavaScript上下文中,以便可以通過頁面中的JavaScript訪問它們。

縮放

Android 1.5 之後支援呼叫如下方法啟用內建縮放:

WebSettings.setBuiltInZoomControls(boolean)

注意:設定了內建縮放,WebView 的寬高又是 wrap_content,將會導致未定義的行為,使用時應該避免這種情況。

構建網頁以支援不同的螢幕密度

螢幕密度是基於螢幕解析度的,低密度的螢幕每英寸可用畫素更少,高密度的螢幕每英寸可用畫素更多,螢幕密度是比較重要的,因為其他因素相同的情況下,根據畫素定義的 UI 元素,在低密度螢幕上顯示較大,在較高螢幕密度的螢幕上顯示較小;為了方便 Android 將實際中的螢幕密度換算成比較廣泛的螢幕密度:高、中和低。

預設情況下,WebView 縮放的網頁,使其繪製的尺寸與中密度螢幕上的預設外觀相匹配,所以在高密度螢幕上適用於 1.5 倍的縮放(畫素較小),在低密度螢幕上適用於 0.75 倍的縮放(畫素較大);從 Android 2.0 開始 WebView 支援 DOM、CSS 及 meta 標籤,幫助 Web 開發人員根據不同的螢幕密度來適配目標螢幕。

下面是處理不同螢幕密度的一些說明:

  1. 使用 window.devicePixelRatio 屬性指定當前裝置的預設縮放因子,也指裝置上物理畫素和裝置獨立畫素(device-independent pixels (dips))的比例,如果 window.devicePixelRatio 的值為 1 ,則該裝置被認為是中密度(mdpi)裝置,並且預設縮放不應用於網頁,如果 window.devicePixelRatio 值為原來的 1.5 倍 ,則該裝置被認為是高密度裝置(hdpi),頁面內容縮放為 1.5 倍;如果 window.devicePixelRatio 值為 0.75,則該裝置被認為是低密度裝置(ldpi),內容縮放為原來的 0.75 倍,用公式表示如下:

window.devicePixelRatio(dpr) = \frac{physical pixel}{dips(css pixel)}

physical pixel = dips * \frac{density}{160} (Android)
  1. 使用 -webkit-device-pixel-ratio CSS 媒體查詢來指定使用此樣式表的螢幕密度,其值應該為 0.75 、1 、1.5,分別指明這些樣式表適用於低密度、中密度、高密度的螢幕裝置,如下面的宣告表明 hdpi.css 只適用於螢幕畫素密度比例為 1.5 的螢幕裝置,也就是適用於高密度螢幕裝置。
 <link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" />

HTML5 視訊支援

如果在應用程式中支援 HTML 視訊,需要啟用硬體加速。

關於硬體加速請參考:Android硬體加速

全屏支援

為了支援全螢幕,如視訊或其他 HTML 內容,需要設定一個 WebChromeClient 並實現 onShowCustomView(View,WebChromeClient.CustomViewCallback) 和 onHideCustomView() 兩個方法:

1. onShowCustomView

通知應用程式當前頁面進入全屏模式,應用程式將以全屏模式包含 Web 內容、視訊以及其他 HTML 的內容。

/**
 * @param view 顯示的View.
 * @param callback 呼叫當前頁退出當前頁
 * full screen mode.
 */
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {};

2. onHideCustomView

通知應用程式當前頁面退出全屏模式,應用程式必須隱藏自定義的 View。

public void onHideCustomView() {}

如果這兩個方法中的任何一個沒有實現,則對應的頁面的 Web 頁面不能進入全屏模式,也可以實現 getVideoLoadingProgressView() 來自定義視訊緩衝時要顯示的檢視。

 public View getVideoLoadingProgressView() {
        return null;
}

HTML5 地理位置 API

針對 Android N 以及 API level > M 的裝置,地理位置 API 僅僅支援以 HTTPs 的方式,如果應用以非 HTTPS 的方式請求地理位置 API onGeolocationPermissionsShowPrompt(String, GeolocationPermissions.Callback) 方法將會被拒絕呼叫。

佈局尺寸

建議將 WebView 的高度設定成固定值或者是 MATCH_PARENT 而不建議使用 WRAP_CONTENT ,如果 WebView 的高度使用了 MATCH_PARENT ,它的父佈局高度實用 WRAP_CONTENT 會導致石梯大小不一致。

將 WebView 的高度設定成 WRAP_CONTENT 將會出現如下行為:

  1. HTML 的高度被設定成了固定值,這意味著相對於 HTML BODY 高度的元素大小可能不正確;
  2. 對於應用程式所在裝置是 Android 4.4 及更早的 SDk, meta 標籤將會被忽略以保證向後的相容性;

不支援使用 WRAP_CONTENT 的佈局寬度。如果使用這樣的寬度,WebView 會嘗試使用其父佈局的寬度。

關於錯誤資料的收集

如果使用者同意,WebView 的一些診斷資料將會以匿名的方式上傳到 Google ,這些資料會幫助 Google 改善 WebView ,每個已初始化 WebView 的應用程式都會收集這些資料,如果想停用該功能需要在清單檔案中進行如下設定:

 <meta-data 
    android:name="android.webkit.WebView.MetricsOptOut"
    android:value="true" />

參考連結:WebView 官網介紹

如果覺得對自己有幫助,可以關注公眾號:jzman-blog,一起交流學習。

2494569-f1ae978df99e1007.jpg
jzman-blog.jpg

相關文章