今天我們來學(xué)習(xí)一個可以顯示網(wǎng)頁的控件WebView。WebView的網(wǎng)頁渲染引擎和Safari、Chrome一樣都是Webkit。使用WebView進行互聯(lián)網(wǎng)程序開發(fā)有以下優(yōu)點:
1、可以打開遠程網(wǎng)址、也可以加載本地Html數(shù)據(jù)
2、可以搭建Java和Javascript交互橋梁
3、WebView控件可以高度定制。
<?xml version="1.0" encoding="utf-8"?> 4、在Activity文件的OnCreate方法中默認(rèn)載入一個百度頁面,點擊按鈕時載入預(yù)設(shè)的網(wǎng)址http://android.yaohuiji.com : 01 | package android.basic.lesson29; |
03 | import android.app.Activity; |
04 | import android.os.Bundle; |
05 | import android.view.View; |
06 | import android.webkit.WebView; |
07 | import android.widget.Button; |
08 | import android.widget.EditText; |
10 | public class MainWebView extends Activity { |
14 | /** Called when the activity is first created. */ |
16 | public void onCreate(Bundle savedInstanceState) { |
17 | super .onCreate(savedInstanceState); |
18 | setContentView(R.layout.main); |
21 | mWebView = (WebView) findViewById(R.id.WebView01); |
22 | Button b1 = (Button) findViewById(R.id.Button01); |
23 | final EditText et = (EditText) findViewById(R.id.EditText01); |
25 | //得到WebSetting對象,設(shè)置支持Javascript的參數(shù) |
26 | mWebView.getSettings().setJavaScriptEnabled( true ); |
30 | mWebView.requestFocus(); |
33 | b1.setOnClickListener( new View.OnClickListener() { |
36 | public void onClick(View v) { |
38 | mWebView.loadUrl(et.getText().toString()); |
5、運行程序,查看效果:
點擊Go按鈕,可以看到本博客出現(xiàn),不過沒有經(jīng)過任何縮放處理,在接下里的例子我們繼續(xù)研究,如何做更多的控制。
二、補充一點基礎(chǔ)知識:關(guān)于WebSettings
1、先看一下WebView的繼承關(guān)系,可以看到它不是在 android.widget包中,而是在android.webkit包中。
2、WebSettings : WebView組件有一個輔助類叫WebSettings,它管理WebView的設(shè)置狀態(tài)。該對象可以通過WebView.getSettings()方法獲得。下面舉幾個例子來說明WebSettings的用法:
//得到WebSettings對象,設(shè)置支持Javascript的參數(shù)
mWebView.getSettings().setJavaScriptEnabled(true);
//設(shè)置可以支持縮放
mWebView.getSettings().setSupportZoom(true);
//設(shè)置默認(rèn)縮放方式尺寸是far
mWebView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
//設(shè)置出現(xiàn)縮放工具
mWebView.getSettings().setBuiltInZoomControls(true);
三、加載assets目錄下的本地網(wǎng)頁
WebView調(diào)用assets目錄下的本地網(wǎng)頁和圖片等資源非常方便,使用形如
wv.loadUrl("file:///android_asset/html/test1.html");
的調(diào)用方法即可,代碼在第四段落里。
在test1中點擊鏈接也可以跳轉(zhuǎn)到test2
四、使用 LoadData 方法加載內(nèi)容
可以在Java文件中或者XML文件中定義HTML的片段,也可以在assets目錄中存放HTML文件,然后使用LoadData加載其中的內(nèi)容,展示出來。下面我們使用第三部分的網(wǎng)頁來演示一下如何使用LoadData方法,并且看看他們之間的區(qū)別。
1、新建項目Lesson29_WebView2
2、新建2個Html文件在assets/html下,內(nèi)容略去,res/layout/main.xml的內(nèi)容也略去了,相信對你來說已經(jīng)不成問題。
3、MainWebView2.java 的內(nèi)容如下:
01 | package android.basic.lesson29; |
03 | import java.io.IOException; |
04 | import java.io.InputStream; |
06 | import org.apache.http.util.ByteArrayBuffer; |
07 | import org.apache.http.util.EncodingUtils; |
09 | import android.app.Activity; |
10 | import android.os.Bundle; |
11 | import android.view.View; |
12 | import android.webkit.WebView; |
13 | import android.widget.Button; |
15 | public class MainWebView2 extends Activity { |
16 | /** Called when the activity is first created. */ |
18 | public void onCreate(Bundle savedInstanceState) { |
19 | super .onCreate(savedInstanceState); |
20 | setContentView(R.layout.main); |
23 | Button b1 = (Button) findViewById(R.id.Button01); |
24 | Button b2 = (Button) findViewById(R.id.Button02); |
26 | final WebView wv = (WebView) findViewById(R.id.WebView01); |
29 | b1.setOnClickListener( new View.OnClickListener() { |
31 | public void onClick(View v) { |
38 | b2.setOnClickListener( new View.OnClickListener() { |
40 | public void onClick(View v) { |
43 | // 讀取assets目錄下的文件需要用到AssetManager對象的Open方法打開文件 |
44 | InputStream is = getAssets().open( "html/test2.html" ); |
45 | // loadData()方法需要的是一個字符串?dāng)?shù)據(jù)所以我們需要把文件轉(zhuǎn)成字符串 |
46 | ByteArrayBuffer baf = new ByteArrayBuffer( 500 ); |
48 | while ((count = is.read()) != - 1 ) { |
51 | data = EncodingUtils.getString(baf.toByteArray(), "utf-8" ); |
52 | } catch (IOException e) { |
56 | wv.loadData(data, "text/html" , "utf-8" ); |
57 | // wv.loadDataWithBaseURL("", data, "text/html", "utf-8", ""); |
4、運行程序單擊第二個按鈕,效果如下:
對比上面的例子,我們可以看到兩個明顯的區(qū)別,其一,圖片沒加載出來,其二鏈接失效,點擊后無法加載test1.html 。
五、兩個和WebView相關(guān)的重要對象:WebChromeClient 和 WebViewClient
和WebView相關(guān)的輔助對象,除了WebSettings以外還有WebChromeClient和WebViewClient。
接下來的這個例子內(nèi)容比較豐富,雖然注釋比較清晰,但是您一次消化起來還是比較困難的,因此您需要的是一點點耐心,多看幾遍,最重要的是自己至少敲代碼敲一遍。
1、在上面的例子中繼續(xù)增加內(nèi)容,增加 test3.html 的內(nèi)容:
06 | < SCRIPT type = text /JavaScript> |
07 | function alertFuction(){ |
12 | function confirmFuction(){ |
18 | < INPUT onclick = alertFuction () type = button value=提醒對話框> |
19 | < INPUT onclick = confirmFuction () type = button value=選擇對話框> |
21 | < A href = "test1.html" >上一頁</ A > |
2、MainWebView3.java的內(nèi)容,請注意注釋內(nèi)容:
001 | package android.basic.lesson29; |
003 | import java.io.FileOutputStream; |
005 | import android.app.Activity; |
006 | import android.app.AlertDialog; |
007 | import android.app.AlertDialog.Builder; |
008 | import android.content.DialogInterface; |
009 | import android.graphics.Bitmap; |
010 | import android.graphics.Canvas; |
011 | import android.graphics.Picture; |
012 | import android.os.Bundle; |
013 | import android.view.KeyEvent; |
014 | import android.view.View; |
015 | import android.webkit.JsPromptResult; |
016 | import android.webkit.JsResult; |
017 | import android.webkit.WebChromeClient; |
018 | import android.webkit.WebView; |
019 | import android.webkit.WebViewClient; |
020 | import android.widget.Button; |
021 | import android.widget.Toast; |
023 | public class MainWebView3 extends Activity { |
025 | /** Called when the activity is first created. */ |
027 | public void onCreate(Bundle savedInstanceState) { |
028 | super .onCreate(savedInstanceState); |
029 | setContentView(R.layout.main); |
032 | Button b1 = (Button) findViewById(R.id.Button01); |
033 | Button b2 = (Button) findViewById(R.id.Button02); |
034 | Button b3 = (Button) findViewById(R.id.Button03); |
036 | final WebView wv = (WebView) findViewById(R.id.WebView01); |
038 | // 覆蓋默認(rèn)后退按鈕的作用,替換成WebView里的查看歷史頁面 |
039 | wv.setOnKeyListener( new View.OnKeyListener() { |
042 | public boolean onKey(View v, int keyCode, KeyEvent event) { |
043 | if (event.getAction() == KeyEvent.ACTION_DOWN) { |
044 | if ((keyCode == KeyEvent.KEYCODE_BACK) && wv.canGoBack()) { |
053 | // 設(shè)置支持Javascript |
054 | wv.getSettings().setJavaScriptEnabled( true ); |
056 | // 定義并綁定按鈕單擊監(jiān)聽器 |
057 | b1.setOnClickListener( new View.OnClickListener() { |
059 | public void onClick(View v) { |
065 | // 定義并綁定按鈕單擊監(jiān)聽器 |
066 | b2.setOnClickListener( new View.OnClickListener() { |
068 | public void onClick(View v) { |
074 | // 定義并綁定按鈕單擊監(jiān)聽器 |
075 | b3.setOnClickListener( new View.OnClickListener() { |
077 | public void onClick(View v) { |
078 | Picture pic = wv.capturePicture(); |
079 | int width = pic.getWidth(); |
080 | int height = pic.getHeight(); |
081 | if (width > 0 && height > 0 ) { |
082 | Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); |
083 | Canvas canvas = new Canvas(bmp); |
086 | String fileName = "sdcard/" + System.currentTimeMillis() + ".png" ; |
087 | FileOutputStream fos = new FileOutputStream(fileName); |
090 | bmp.compress(Bitmap.CompressFormat.PNG, 90 , fos); |
093 | Toast.makeText(getApplicationContext(), "截圖成功,文件名是:" + fileName, Toast.LENGTH_SHORT).show(); |
094 | } catch (Exception e) { |
101 | // 創(chuàng)建WebViewClient對象 |
102 | WebViewClient wvc = new WebViewClient() { |
105 | public boolean shouldOverrideUrlLoading(WebView view, String url) { |
106 | Toast.makeText(getApplicationContext(), "WebViewClient.shouldOverrideUrlLoading" , Toast.LENGTH_SHORT) |
108 | // 使用自己的WebView組件來響應(yīng)Url加載事件,而不是使用默認(rèn)瀏覽器器加載頁面 |
110 | // 記得消耗掉這個事件。給不知道的朋友再解釋一下,Android中返回True的意思就是到此為止吧,事件就會不會冒泡傳遞了,我們稱之為消耗掉 |
115 | public void onPageStarted(WebView view, String url, Bitmap favicon) { |
116 | Toast.makeText(getApplicationContext(), "WebViewClient.onPageStarted" , Toast.LENGTH_SHORT).show(); |
117 | super .onPageStarted(view, url, favicon); |
121 | public void onPageFinished(WebView view, String url) { |
122 | Toast.makeText(getApplicationContext(), "WebViewClient.onPageFinished" , Toast.LENGTH_SHORT).show(); |
123 | super .onPageFinished(view, url); |
127 | public void onLoadResource(WebView view, String url) { |
128 | Toast.makeText(getApplicationContext(), "WebViewClient.onLoadResource" , Toast.LENGTH_SHORT).show(); |
129 | super .onLoadResource(view, url); |
134 | // 設(shè)置WebViewClient對象 |
135 | wv.setWebViewClient(wvc); |
137 | // 創(chuàng)建WebViewChromeClient |
138 | WebChromeClient wvcc = new WebChromeClient() { |
142 | public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { |
143 | // 構(gòu)建一個Builder來顯示網(wǎng)頁中的alert對話框 |
144 | Builder builder = new Builder(MainWebView3. this ); |
145 | builder.setTitle( "計算1+2的值" ); |
146 | builder.setMessage(message); |
147 | builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() { |
149 | public void onClick(DialogInterface dialog, int which) { |
153 | builder.setCancelable( false ); |
160 | public void onReceivedTitle(WebView view, String title) { |
161 | MainWebView3. this .setTitle( "可以用onReceivedTitle()方法修改網(wǎng)頁標(biāo)題" ); |
162 | super .onReceivedTitle(view, title); |
167 | public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { |
168 | Builder builder = new Builder(MainWebView3. this ); |
169 | builder.setTitle( "刪除確認(rèn)" ); |
170 | builder.setMessage(message); |
171 | builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() { |
174 | public void onClick(DialogInterface dialog, int which) { |
179 | builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() { |
182 | public void onClick(DialogInterface dialog, int which) { |
187 | builder.setCancelable( false ); |
195 | public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, |
196 | JsPromptResult result) { |
198 | return super .onJsPrompt(view, url, message, defaultValue, result); |
202 | // 設(shè)置setWebChromeClient對象 |
203 | wv.setWebChromeClient(wvcc); |
3、運行程序,查看結(jié)果:
啟動起來時的畫面
點擊第一個按鈕,我們可以看到WebViewClient對象中定義的方法的確被調(diào)用了。
點擊第二個按鈕,我們看到加載的網(wǎng)頁中有兩個按鈕,我們知道默認(rèn)情況下Android會直接忽略掉由javascript弄出來的alert等彈出信息,除非我們在WebChromeClient中覆蓋onJsAlert()方法和onJsConfirm()方法,讓我們分別點擊它們看看效果。
接下來我們再頁面中跳轉(zhuǎn)幾次后,使用后退按鈕,查看我們是否屏蔽了Activity默認(rèn)的行為,結(jié)果當(dāng)然是屏蔽了^_^,這一段代碼沒有留意的同學(xué)回去在看一下吧。
接下來我們把頁面切換到這一個網(wǎng)頁:
然后我們按下第三個保存圖片的按鈕,不出意外的話我們截取到了該頁的完整圖片,并把它保存到了sdcard中了,我在這里展示一下我截取的效果給你看,別被它清晰的效果嚇住就行^_^
好了,因為篇幅關(guān)系,我們關(guān)于WebView的功能也只能介紹到這里,關(guān)于WebView的其它功能我們在接下來的項目中會涉及到,到時候我們再一起學(xué)習(xí),本講就到這里吧,各位下次再見。