原來你是這樣的WebView(一)

隨着Html5的快速發展,越來越多的App對WebView的使用越來越頻繁,不再像以前一樣只需要調用webview.loadurl(url)就可以滿足基本的使用,本文就對目前WebView的常用用法進行總結介紹,希望能幫到一些小夥伴…

1. WebView是個什麼鬼

一個用來展示web界面的View, WebView可以在自己的瀏覽器或者Activity中進行內容展示,採用了WebKit渲染引擎來顯示網頁,包括歷史導航,前一頁,後一頁,放大,縮小,執行搜索文本等功能;如果你想在項目中使用WebView,需要添加一個訪問網絡的權限:

uses-permission android:name=”android.permission.INTERNET”

2. WebView的基本使用

2.1 發送Intent調用系統瀏覽器打開加載頁

WebView在默認情況下,不支持瀏覽器中例如widget插件,默認關閉Js交互,並忽略網頁上將被忽略;如果你只想展示一個頁面,但是並不需要交互,那使用webview是比較合適的; 如果你想實現一個全面的web頁面,那麼你可以開啓一個URL意圖來使用瀏覽器打開當前URL,但一般爲了用戶體驗,這種用法的使用還是比較少的;示例如下

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

2.2 調用webview.loadUrl(url)來加載

2.2.1 webview.loadUrl(url)加載網絡地址

當然,多數情況下,我們會在layout文件中定義一個webview控件,然後在Activity中的onCreate裏面加載我們想要看到的url界面,使用如下:

    //第一種寫法,常用格式
    WebView webView = (WebView) findViewById(R.id.webview);
    webView.loadUrl("http://www.baidu.com");
    //注意:如果不想彈出系統瀏覽器進行界面顯示,需要重寫該方法
    webView.setWebViewClient(new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            //返回值沒有關係
            return super.shouldOverrideUrlLoading(view,url);
        }
    });

    //第二種寫法,直接在setContentView中傳入webview
    WebView webView = new WebView(this);
    webView.loadUrl("http://www.baidu.com");
    setContentView(webView);
    webView.setWebViewClient(new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            //返回值沒有關係
            return super.shouldOverrideUrlLoading(view,url);
        }
    });

注意:如果不想彈出系統瀏覽器進行界面顯示,需要重寫shouldOverrideUrlLoading方法

2.2.2 webview.loadUrl(url)加載apk包內html文件

webview不但可以加載網絡頁面,也可以加載apk包下的html文件,將html文件放在項目assets資源目錄下,然後調用以下代碼即可

webView.loadUrl("file:///android_asset/test.html");

2.2.3 webview.loadUrl(url)加載SD卡下的html文件

webview加載SD卡根目錄下test.html文件代碼如下:

webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

2.3 webview加載HTML格式字符串

除了可以加載網頁之外,webview也可以加載HTML格式的字符串;主要是兩個方法,一個webView.loadData(data,mimeType,encoding);來展示,一個是webView.loadDataWithBaseURL(baseUrl,data,mimeType,encoding,historyUrl);. 如果是帶有中文的數據,默認顯示會展示亂碼,可以有兩種方式來解決亂碼;我們先來看一下如果都是英文數據該如何展示:

String data = "<html><body>You scored <b>Egglish</b> points.</body></html>";
webView.loadData(summary, "text/html", null);

展示效果如圖所示:

如果包含了中文,會顯示亂碼:

第一種修改方式,可以在loadData中更改第二個參數,注意:如果將第三個參數更改爲”UTF-8”,依然會是亂碼;正確修改如下:

String data = "<html><body>You scored <b>中文測試</b> points.</body></html>";
webView.loadData(data, "text/html; charset=UTF-8", null);

顯示效果如下:

原因如下:

如果用 loadDataWithBaseURL時,如果不傳入URL時,刷新會造成白屏,因爲刷新時調用的的是reload方法,reload是根據傳入的URL進行一次重新加載即再次loadUrl(url),不傳入URL時,默認的的URL是about:blank;使用loadData,刷新只是從緩存裏面取,但是在4.0以上的,如果按照API裏所寫的loadData(data, “UTF-8”, null);時會亂碼,如果寫成loadData(data, "text/html; charset=UTF-8", null);loadData最終的機制是會把傳入的三個參數拼接在一起,然後再進行loadUrl操作,參數就是data, "text/html; charset=UTF-8", null這三個進行拼裝,加入text/html; charset=UTF-8就相當於限定了頁面的字符

上面的一種修改方式可以適配大多數機型,但依然有少部分機型會顯示亂碼,可能與系統底層文件修改有關,所以就有了另一種修改方式,調用loadDataWithBaseURL方法,修改如下:

String data = "<html><body>You scored <b>中文測試</b> points.</body></html>";
webView.loadDataWithBaseURL(null,summary,"text/html","UTF-8",null);

3. 自定義你的webview

WebView除了基本的用法以外,還可以進行自定義來達到你想要的效果,比如創建一個匿名WebChromeClient來輔助WebView處理Javascript的對話框,網站圖標,網站title,加載進度等;也可以創建一個匿名WebViewClient ,來幫助WebView處理各種通知、請求事件等;當然,也可以啓用 WebSettings,來開啓Js交互等等,下面我們就來逐一介紹.

3.1 WebChromeClient

方法中的代碼均有Android端自行處理,實現方式可以寫一個匿名內部類,或者寫一個WebChromeClient類,然後調用webview.setWebChromeClient(mWebChromeClient);代碼示例如下:

webView.setWebChromeClient(new WebChromeClient() {
    //獲取網頁的加載進度,因有的網頁是採用分模塊加載,所以進度值並非只是一次1~100;可以爲: 29~100;30~100;
    @Override
    public void onProgressChanged(WebView view, int progress) {
        Log.e(TAG,"progress="+progress);
    }

    //獲取當前網頁中的Title值來設置給自己的title
    //注意:如果無網,獲取的 title= 找不到網頁
    //所以開發者可以在接受到onReceiveError的回調後,不要在使用當前獲取的title值了
    @Override
    public void onReceivedTitle(WebView view, String title) {
        Log.e(TAG,"title="+title);
    }
    //獲取當前網頁的icon,拿到後,會獲取一個Bitmap對象,你想幹嘛就幹嘛
    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        super.onReceivedIcon(view, icon);
    }

});

以上爲簡單用法,下面我們對 onJsAlert(), onJsPrompt(),onJsConfirm()進行逐一分析;在WebChromeClient類裏可以重寫這三個方法,此時WebView中加載的html中如果執行alert("alert...."); , confirm("confirm..."); , prompt("prompt...", "defaultValue");這三個方法,該類就會監聽到執行對應的三個方法。我們可以讓這三個方法的返回值爲true ,即自定義此方法。在裏面寫入自己定義的Dialog,便可實現html與Activity交互。

注意 JsResult 此類需要在操作時,如果操作則 result.cofirm(). 取消則 result.cancel(); 還必須這每一個方法中寫入 dialog.setOnkeyListener(); 方法來監聽Back鍵,listener中    要寫 result.cancel(); 否則系統沒有消費這個事件,會出錯。

3.1.1 自定義onJsAlert

什麼是Javascript Alert?

Alert是一種提示信息或者警告信息的對話框,一旦顯示到用戶面前,只能點擊OK才能關閉.

通常一般的實現類似:

<html>
   <SCRIPT type="text/javascript">
       alert('This is alert dialog !')
   </SCRIPT>
</html>

效果圖如下:

onJsAlert API 介紹:

public boolean onJsAlert (WebView view, String url, String message, JsResult result)

Tell the client to display a javascript alert dialog. If the client returns true, WebView will assume that the client will handle the dialog. If the client returns false, it will continue execution.

告知客戶端將顯示一個alert dialog; 如果方法返回了true, 那麼webview就會來自行處理這個dialog; 如果返回了false,則會繼續執行下去,webview不進行處理;

在Android中,我們一般重寫onJsAlert方法,會將參數中的message信息用Toast的形式彈出以告知用戶,代碼如下;

@Override
   public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
       Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
       ////因爲沒有綁定事件,需要強行confirm,否則頁面會變黑顯示不了內容。
       result.confirm();
       return true;
   }

或者我們可以自行彈出一個Dialog,覆蓋默認的顯示界面,代碼如下:

@Override
   public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("測試自定義對話框").setMessage(message)
               .setPositiveButton("確定", null);
       //這裏不需要綁定按鍵事件
       //可自行屏蔽keycode按鍵
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() {
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) {
               Log.e(TAG,"keyCode==" + keyCode + "event=" + event);
               return true;
           }
       });
       //禁止響應按back鍵的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       result.confirm();//因爲沒有綁定事件,需要強行confirm,否則頁面會變黑顯示不了內容。
       return true;
   }

3.1.2 自定義onJsConfirm

用法與onJsAlert基本一樣,直接上代碼:

@Override
   public boolean onJsConfirm(WebView view, String url, String message,
                              final JsResult result) {
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("webview測試confirm對話框")
               .setMessage(message)
               .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       result.confirm();
                   }
               })
               .setNeutralButton("取消", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       result.cancel();
                   }
       });
       builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
           @Override
           public void onCancel(DialogInterface dialog) {
               result.cancel();
           }
       });

       //屏蔽keycode的按鍵,避免按鍵後導致對話框消息而頁面無法再彈出對話框的問題
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() {
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) {
               Log.e(TAG, "keyCode==" + keyCode + "event=" + event);
               return true;
           }
       });
       //禁止響應按back鍵的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       return true;
   }

3.1.3 自定義 onJsPrompt

直接上代碼,大致用法一樣,只不過個別參數不同:

@Override
   public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("webview測試prompt對話框").setMessage(message);

       final EditText et = new EditText(view.getContext());
       et.setSingleLine();
       et.setText(defaultValue);
       builder.setView(et);
       builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog, int which) {
               result.confirm(et.getText().toString());
           }
       }).setNeutralButton("取消", new DialogInterface.OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog, int which) {
               result.cancel();
           }
       });

       //屏蔽keycode按鍵,避免按鍵後導致對話框消息而頁面無法再彈出對話框的問題
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() {
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) {
               Log.e(TAG, "keyCode==" + keyCode + "event=" + event);
               return true;
           }
       });

       //禁止響應按back鍵的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       return true;
   }

4. 使用websettings讓你的webview更加強大

webview獲取到websettings之後,可以對當前的webview進行各種設置,如 Js交互開啓,縮放,支持插件等等,我們直接以代碼爲例,代碼中對每個功能點都進行了詳細說明,請小夥伴參閱;

WebSettings webSettings = webView.getSettings();

   //支持獲取手勢焦點,輸入用戶名、密碼或其他
   webView.requestFocusFromTouch();
   //支持js交互
   webSettings.setJavaScriptEnabled(true);
   webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通過JS打開新窗口

   //設置自適應屏幕,需要與setLoadWithOverviewMode合用
   webSettings.setUseWideViewPort(true);  //可以將圖片調整到適合webview的大小
   webSettings.setLoadWithOverviewMode(true); // 縮放至屏幕的大小

   //支持縮放,默認爲true。是setBuiltInZoomControls的前提。
   //若setSupportZoom是false,則該WebView不可縮放,這個不管setBuiltInZoomControls設置什麼都不能縮放。
   webSettings.setSupportZoom(true);
   webSettings.setBuiltInZoomControls(true); //設置內置的縮放控件

   webSettings.setDisplayZoomControls(false); //隱藏原生的縮放控件

   //提高渲染的優先級
   webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);

   webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支持內容重新佈局
   webSettings.supportMultipleWindows();  //支持多窗口
   webSettings.setAllowFileAccess(true);  //設置可以訪問文件
   webSettings.setLoadsImagesAutomatically(true);  //支持自動加載圖片
   webSettings.setDefaultTextEncodingName("utf-8");//設置編碼格式

好了,上面就是webview的一些簡單用法,後面我們將對webview的緩存機制,前進回退操作,與js互調,避免webview內存泄露等問題進行逐一分析,希望我的文字能在你需要的時候幫到你, 願大家有美好的一天…..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章