適于自學(xué)的Andorid學(xué)習(xí)指南,基于Android 2.2和2.3版本講解
《Android學(xué)習(xí)指南》目錄
RSS
第二十九講:WebView學(xué)習(xí)指南
19 Aug
本講內(nèi)容:WebView的使用方法
今天我們來(lái)學(xué)習(xí)一個(gè)可以顯示網(wǎng)頁(yè)的控件WebView。WebView的網(wǎng)頁(yè)渲染引擎和Safari、Chrome一樣都是Webkit。使用WebView進(jìn)行互聯(lián)網(wǎng)程序開(kāi)發(fā)有以下優(yōu)點(diǎn):
1、可以打開(kāi)遠(yuǎn)程網(wǎng)址、也可以加載本地Html數(shù)據(jù)
2、可以搭建Java和Javascript交互橋梁
3、WebView控件可以高度定制。
下面我們通過(guò)幾個(gè)例子來(lái)共同學(xué)習(xí)WebView的使用方法。
一、先做一個(gè)例子熱熱身看看效果,例子:通過(guò)WebView訪問(wèn)本博客 http://android.yaohuiji.com
1、先來(lái)一個(gè)簡(jiǎn)單的例子,新建一個(gè)項(xiàng)目Lesson29_WebView
2、因?yàn)橐L問(wèn)互聯(lián)網(wǎng)所以先在AndroidManifest.xml中設(shè)定權(quán)限:
view source
print?
01 <?xml version="1.0" encoding="utf-8"?>
02 <MANIFEST android:versionname="1.0" android:versioncode="1" package="android.basic.lesson29" xmlns:android="http://schemas.android.com/apk/res/android">
03 <APPLICATION android:label="@string/app_name" android:icon="@drawable/icon">
04 <ACTIVITY android:label="@string/app_name" android:name=".MainWebView">
05 <INTENT -filter>
06 <ACTION android:name="android.intent.action.MAIN" />
07 <CATEGORY android:name="android.intent.category.LAUNCHER" />
08 </INTENT>
09 </ACTIVITY>
10
11 </APPLICATION>
12 <USES android:minsdkversion="8" -sdk />
13 <USES android:name="android.permission.INTERNET" -permission />
14 </MANIFEST>
3、在res/layout/main.xml中放置一個(gè)輸入框,一個(gè)按鈕和一個(gè)WebView:
<?xml version="1.0" encoding="utf-8"?> 4、在Activity文件的OnCreate方法中默認(rèn)載入一個(gè)百度頁(yè)面,點(diǎn)擊按鈕時(shí)載入預(yù)設(shè)的網(wǎng)址http://android.yaohuiji.com :view source
print?
01 package android.basic.lesson29;
02
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;
09
10 public class MainWebView extends Activity {
11
12 WebView mWebView;
13
14 /** Called when the activity is first created. */
15 @Override
16 public void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout.main);
19
20 //定義UI組件
21 mWebView = (WebView) findViewById(R.id.WebView01);
22 Button b1 = (Button) findViewById(R.id.Button01);
23 final EditText et = (EditText) findViewById(R.id.EditText01);
24
25 //得到WebSetting對(duì)象,設(shè)置支持Javascript的參數(shù)
26 mWebView.getSettings().setJavaScriptEnabled(true);
27 //載入U(xiǎn)RL
28 mWebView.loadUrl("http://www.baidu.com");
29 //使頁(yè)面獲得焦點(diǎn)
30 mWebView.requestFocus();
31
32 //給按鈕綁定單擊監(jiān)聽(tīng)器
33 b1.setOnClickListener(new View.OnClickListener() {
34
35 @Override
36 public void onClick(View v) {
37 //訪問(wèn)編輯框中的網(wǎng)址
38 mWebView.loadUrl(et.getText().toString());
39 }
40 });
41
42 }
43 }
5、運(yùn)行程序,查看效果:
點(diǎn)擊Go按鈕,可以看到本博客出現(xiàn),不過(guò)沒(méi)有經(jīng)過(guò)任何縮放處理,在接下里的例子我們繼續(xù)研究,如何做更多的控制。
二、補(bǔ)充一點(diǎn)基礎(chǔ)知識(shí):關(guān)于WebSettings
1、先看一下WebView的繼承關(guān)系,可以看到它不是在 android.widget包中,而是在android.webkit包中。
2、WebSettings : WebView組件有一個(gè)輔助類叫WebSettings,它管理WebView的設(shè)置狀態(tài)。該對(duì)象可以通過(guò)WebView.getSettings()方法獲得。下面舉幾個(gè)例子來(lái)說(shuō)明WebSettings的用法:
//得到WebSettings對(duì)象,設(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)頁(yè)
WebView調(diào)用assets目錄下的本地網(wǎng)頁(yè)和圖片等資源非常方便,使用形如
wv.loadUrl("file:///android_asset/html/test1.html");
的調(diào)用方法即可,代碼在第四段落里。
在test1中點(diǎn)擊鏈接也可以跳轉(zhuǎn)到test2
四、使用 LoadData 方法加載內(nèi)容
可以在Java文件中或者XML文件中定義HTML的片段,也可以在assets目錄中存放HTML文件,然后使用LoadData加載其中的內(nèi)容,展示出來(lái)。下面我們使用第三部分的網(wǎng)頁(yè)來(lái)演示一下如何使用LoadData方法,并且看看他們之間的區(qū)別。
1、新建項(xiàng)目Lesson29_WebView2
2、新建2個(gè)Html文件在assets/html下,內(nèi)容略去,res/layout/main.xml的內(nèi)容也略去了,相信對(duì)你來(lái)說(shuō)已經(jīng)不成問(wèn)題。
3、MainWebView2.java 的內(nèi)容如下:
view source
print?
01 package android.basic.lesson29;
02
03 import java.io.IOException;
04 import java.io.InputStream;
05
06 import org.apache.http.util.ByteArrayBuffer;
07 import org.apache.http.util.EncodingUtils;
08
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;
14
15 public class MainWebView2 extends Activity {
16 /** Called when the activity is first created. */
17 @Override
18 public void onCreate(Bundle savedInstanceState) {
19 super.onCreate(savedInstanceState);
20 setContentView(R.layout.main);
21
22 //定義UI組件
23 Button b1 = (Button) findViewById(R.id.Button01);
24 Button b2 = (Button) findViewById(R.id.Button02);
25
26 final WebView wv = (WebView) findViewById(R.id.WebView01);
27
28 //定義并綁定按鈕單擊監(jiān)聽(tīng)器
29 b1.setOnClickListener(new View.OnClickListener() {
30 @Override
31 public void onClick(View v) {
32 //加載URL assets目錄下的內(nèi)容可以用 "file:///android_asset" 前綴
33 wv.loadUrl("file:///android_asset/html/test1.html");
34 }
35 });
36
37 //定義并綁定按鈕單擊監(jiān)聽(tīng)器
38 b2.setOnClickListener(new View.OnClickListener() {
39 @Override
40 public void onClick(View v) {
41 String data = "";
42 try {
43 // 讀取assets目錄下的文件需要用到AssetManager對(duì)象的Open方法打開(kāi)文件
44 InputStream is = getAssets().open("html/test2.html");
45 // loadData()方法需要的是一個(gè)字符串?dāng)?shù)據(jù)所以我們需要把文件轉(zhuǎn)成字符串
46 ByteArrayBuffer baf = new ByteArrayBuffer(500);
47 int count = 0;
48 while ((count = is.read()) != -1) {
49 baf.append(count);
50 }
51 data = EncodingUtils.getString(baf.toByteArray(), "utf-8");
52 } catch (IOException e) {
53 e.printStackTrace();
54 }
55 // 下面兩種方法都可以加載成功
56 wv.loadData(data, "text/html", "utf-8");
57 // wv.loadDataWithBaseURL("", data, "text/html", "utf-8", "");
58 }
59 });
60
61 }
62 }
4、運(yùn)行程序單擊第二個(gè)按鈕,效果如下:
對(duì)比上面的例子,我們可以看到兩個(gè)明顯的區(qū)別,其一,圖片沒(méi)加載出來(lái),其二鏈接失效,點(diǎn)擊后無(wú)法加載test1.html 。
五、兩個(gè)和WebView相關(guān)的重要對(duì)象:WebChromeClient 和 WebViewClient
和WebView相關(guān)的輔助對(duì)象,除了WebSettings以外還有WebChromeClient和WebViewClient。
接下來(lái)的這個(gè)例子內(nèi)容比較豐富,雖然注釋比較清晰,但是您一次消化起來(lái)還是比較困難的,因此您需要的是一點(diǎn)點(diǎn)耐心,多看幾遍,最重要的是自己至少敲代碼敲一遍。
1、在上面的例子中繼續(xù)增加內(nèi)容,增加 test3.html 的內(nèi)容:
view source
print?
01 <HTML xmlns="http://www.w3.org/1999/xhtml">
02
03 <HTML xmlns="http://www.w3.org/1999/xhtml">
04 <HEAD>
05
06 <SCRIPT type=text/JavaScript>
07 function alertFuction(){
08 var a=1;
09 var b=2
10 alert(a+b);
11 }
12 function confirmFuction(){
13 confirm("你確定要?jiǎng)h除嗎?")
14 }
15 </SCRIPT>
16
17 對(duì)話框測(cè)試
18 <INPUT onclick=alertFuction() type=button value=提醒對(duì)話框>
19 <INPUT onclick=confirmFuction() type=button value=選擇對(duì)話框>
20
21 <A href="test1.html">上一頁(yè)</A>
2、MainWebView3.java的內(nèi)容,請(qǐng)注意注釋內(nèi)容:
view source
print?
001 package android.basic.lesson29;
002
003 import java.io.FileOutputStream;
004
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;
022
023 public class MainWebView3 extends Activity {
024
025 /** Called when the activity is first created. */
026 @Override
027 public void onCreate(Bundle savedInstanceState) {
028 super.onCreate(savedInstanceState);
029 setContentView(R.layout.main);
030
031 // 定義UI組件
032 Button b1 = (Button) findViewById(R.id.Button01);
033 Button b2 = (Button) findViewById(R.id.Button02);
034 Button b3 = (Button) findViewById(R.id.Button03);
035
036 final WebView wv = (WebView) findViewById(R.id.WebView01);
037
038 // 覆蓋默認(rèn)后退按鈕的作用,替換成WebView里的查看歷史頁(yè)面
039 wv.setOnKeyListener(new View.OnKeyListener() {
040
041 @Override
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()) {
045 wv.goBack();
046 return true;
047 }
048 }
049 return false;
050 }
051 });
052
053 // 設(shè)置支持Javascript
054 wv.getSettings().setJavaScriptEnabled(true);
055
056 // 定義并綁定按鈕單擊監(jiān)聽(tīng)器
057 b1.setOnClickListener(new View.OnClickListener() {
058 @Override
059 public void onClick(View v) {
060 // 加載URL assets目錄下的內(nèi)容可以用 "file:///android_asset" 前綴
061 wv.loadUrl("file:///android_asset/html/test1.html");
062 }
063 });
064
065 // 定義并綁定按鈕單擊監(jiān)聽(tīng)器
066 b2.setOnClickListener(new View.OnClickListener() {
067 @Override
068 public void onClick(View v) {
069 // 加載URL assets目錄下的內(nèi)容可以用 "file:///android_asset" 前綴
070 wv.loadUrl("file:///android_asset/html/test3.html");
071 }
072 });
073
074 // 定義并綁定按鈕單擊監(jiān)聽(tīng)器
075 b3.setOnClickListener(new View.OnClickListener() {
076 @Override
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);
084 pic.draw(canvas);
085 try {
086 String fileName = "sdcard/" + System.currentTimeMillis() + ".png";
087 FileOutputStream fos = new FileOutputStream(fileName);
088
089 if (fos != null) {
090 bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
091 fos.close();
092 }
093 Toast.makeText(getApplicationContext(), "截圖成功,文件名是:" + fileName, Toast.LENGTH_SHORT).show();
094 } catch (Exception e) {
095 e.printStackTrace();
096 }
097 }
098 }
099 });
100
101 // 創(chuàng)建WebViewClient對(duì)象
102 WebViewClient wvc = new WebViewClient() {
103
104 @Override
105 public boolean shouldOverrideUrlLoading(WebView view, String url) {
106 Toast.makeText(getApplicationContext(), "WebViewClient.shouldOverrideUrlLoading", Toast.LENGTH_SHORT)
107 .show();
108 // 使用自己的WebView組件來(lái)響應(yīng)Url加載事件,而不是使用默認(rèn)瀏覽器器加載頁(yè)面
109 wv.loadUrl(url);
110 // 記得消耗掉這個(gè)事件。給不知道的朋友再解釋一下,Android中返回True的意思就是到此為止吧,事件就會(huì)不會(huì)冒泡傳遞了,我們稱之為消耗掉
111 return true;
112 }
113
114 @Override
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);
118 }
119
120 @Override
121 public void onPageFinished(WebView view, String url) {
122 Toast.makeText(getApplicationContext(), "WebViewClient.onPageFinished", Toast.LENGTH_SHORT).show();
123 super.onPageFinished(view, url);
124 }
125
126 @Override
127 public void onLoadResource(WebView view, String url) {
128 Toast.makeText(getApplicationContext(), "WebViewClient.onLoadResource", Toast.LENGTH_SHORT).show();
129 super.onLoadResource(view, url);
130 }
131
132 };
133
134 // 設(shè)置WebViewClient對(duì)象
135 wv.setWebViewClient(wvc);
136
137 // 創(chuàng)建WebViewChromeClient
138 WebChromeClient wvcc = new WebChromeClient() {
139
140 // 處理Alert事件
141 @Override

142 public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
143 // 構(gòu)建一個(gè)Builder來(lái)顯示網(wǎng)頁(yè)中的alert對(duì)話框
144 Builder builder = new Builder(MainWebView3.this);
145 builder.setTitle("計(jì)算1+2的值");
146 builder.setMessage(message);
147 builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
148 @Override
149 public void onClick(DialogInterface dialog, int which) {
150 result.confirm();
151 }
152 });
153 builder.setCancelable(false);
154 builder.create();
155 builder.show();
156 return true;
157 }
158
159 @Override
160 public void onReceivedTitle(WebView view, String title) {
161 MainWebView3.this.setTitle("可以用onReceivedTitle()方法修改網(wǎng)頁(yè)標(biāo)題");
162 super.onReceivedTitle(view, title);
163 }
164
165 // 處理Confirm事件
166 @Override
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() {
172
173 @Override
174 public void onClick(DialogInterface dialog, int which) {
175 result.confirm();
176 }
177
178 });
179 builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
180
181 @Override
182 public void onClick(DialogInterface dialog, int which) {
183 result.cancel();
184 }
185
186 });
187 builder.setCancelable(false);
188 builder.create();
189 builder.show();
190 return true;
191 }
192
193 // 處理提示事件
194 @Override
195 public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
196 JsPromptResult result) {
197 // 看看默認(rèn)的效果
198 return super.onJsPrompt(view, url, message, defaultValue, result);
199 }
200 };
201
202 // 設(shè)置setWebChromeClient對(duì)象
203 wv.setWebChromeClient(wvcc);
204 }
205 }
3、運(yùn)行程序,查看結(jié)果:
啟動(dòng)起來(lái)時(shí)的畫(huà)面
點(diǎn)擊第一個(gè)按鈕,我們可以看到WebViewClient對(duì)象中定義的方法的確被調(diào)用了。
點(diǎn)擊第二個(gè)按鈕,我們看到加載的網(wǎng)頁(yè)中有兩個(gè)按鈕,我們知道默認(rèn)情況下Android會(huì)直接忽略掉由javascript弄出來(lái)的alert等彈出信息,除非我們?cè)赪ebChromeClient中覆蓋onJsAlert()方法和onJsConfirm()方法,讓我們分別點(diǎn)擊它們看看效果。
接下來(lái)我們?cè)夙?yè)面中跳轉(zhuǎn)幾次后,使用后退按鈕,查看我們是否屏蔽了Activity默認(rèn)的行為,結(jié)果當(dāng)然是屏蔽了^_^,這一段代碼沒(méi)有留意的同學(xué)回去在看一下吧。
接下來(lái)我們把頁(yè)面切換到這一個(gè)網(wǎng)頁(yè):
然后我們按下第三個(gè)保存圖片的按鈕,不出意外的話我們截取到了該頁(yè)的完整圖片,并把它保存到了sdcard中了,我在這里展示一下我截取的效果給你看,別被它清晰的效果嚇住就行^_^
好了,因?yàn)槠P(guān)系,我們關(guān)于WebView的功能也只能介紹到這里,關(guān)于WebView的其它功能我們?cè)诮酉聛?lái)的項(xiàng)目中會(huì)涉及到,到時(shí)候我們?cè)僖黄饘W(xué)習(xí),本講就到這里吧,各位下次再見(jiàn)。
4 Comments
Posted in 1.Android基礎(chǔ)篇
Tags: AssetManager, onJsAlert, onJsConfirm, onReceivedTitle, WebChromeClient, WebSettings, WebView, WebViewClient
Leave a Reply
Name (required)
Mail (will not be published) (required)
Website
Comment
Samcheung
2010/11/26 at 12:07 pm
老師,怎么我截圖只能截到一個(gè)屏幕大小,而不是整個(gè)圖片?
Reply
tcwkid
2010/11/29 at 10:53 pm
講的很詳細(xì) 很好
Reply
antoon_nee
2010/12/16 at 8:21 pm
請(qǐng)問(wèn)如果頁(yè)面有多個(gè)alert效果。如何在onJsAlert方法中分別設(shè)定不同的顯示效果呢?
Reply
Anonymous
2011/01/10 at 3:16 pm
[...] [...]
Reply
Search
文章分類
0.Java基礎(chǔ)講座 (23) 1.Android基礎(chǔ)篇 (52) 2.Android項(xiàng)目實(shí)訓(xùn)篇 (10) 3.Android提高篇 (1) a.Android開(kāi)發(fā)小知識(shí) (23) b.Android教學(xué)視頻 (4) c.Android Web設(shè)計(jì) (1)
日歷
February 2011 M T W T F S S
« Jan
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
Archives
January 2011(3) December 2010(8) November 2010(6) October 2010(6) September 2010(22) August 2010(31) July 2010(31)
Tags
AbsoluteLayout adt android android.util.Log android 2.2 android snake architecture Button collapse custom dip eclipse3.6 emulator emulator.exe FrameLayout gravity HelloAndroid hello world Hierarchyview.bat layout layout_gravity layout_span LinearLayout LogCat MusicPlayer notepad onSaveInstanceState padding phone RatingBar Recommended color RelativeLayout scale sdk tools shrink sms sqlite stretch Style TableLayout TableRow Thread video View ViewGroup
Recent Comments
Ivan Ek: I intended to draft you that tiny remark in order to give many thanks again just for the spectacular... Jang: 最上面的“colection”錯(cuò)了,改正:collectio n 集合之間的關(guān)系圖能譯成中文嗎 Jang: 集合之間的關(guān)系圖能譯成中文嗎 Jang: “內(nèi)部類對(duì)象中不能有靜態(tài)成員,原因很簡(jiǎn)單,內(nèi)部類 的實(shí)例對(duì)象是外部類實(shí)例對(duì)象的一個(gè)成員。” 在這話里內(nèi)部類的實(shí)例對(duì)象是外部類實(shí)例對(duì)象的一個(gè)成員,跟內(nèi)部類 對(duì)象能不能有靜態(tài)成員.有什么關(guān)系呢? wang: 期待中
Blogroll
androgames android.git.kernel.org Android官方鏡像 androlib easyicon html5china inspire of site moandroid Yao's Tech Blog 前端觀察
Post Views
《Android學(xué)習(xí)指南》目錄 第一講:Android開(kāi)發(fā)環(huán)境的搭建 第十七講:對(duì)話框 Android Dia... 第二講:Android系統(tǒng)構(gòu)架分析和應(yīng)用... 第五講:用戶界面 View(一) 第九講:用戶界面 View(四) 第十六講:菜單 Android Menu 第四講:Activity入門指南 第十講:用戶界面 View(五) 第三講:Android模擬器的使用
Meta
Log in Entries RSS Comments RSS WordPress.org
ChocoTheme by .css{mayo} | powered by WordPress
Entries (RSS) and Comments (RSS)
愛(ài)華網(wǎng)本文地址 » http://www.klfzs.com/a/25101012/124103.html
愛(ài)華網(wǎng)

