今天我们来学习一个可以显示网页的控件WebView。WebView的网页渲染引擎和Safari、Chrome一样都是Webkit。使用WebView进行互联网程序开发有以下优点:
1、可以打开远程网址、也可以加载本地Html数据
2、可以搭建Java和Javascript交互桥梁
3、WebView控件可以高度定制。
下面我们通过几个例子来共同学习WebView的使用方法。
一、先做一个例子热热身看看效果,例子:通过WebView访问博客 http://android.yaohuiji.com
1、先来一个简单的例子,新建一个项目Lesson29_WebView
2、因为要访问互联网所以先在AndroidManifest.xml中设定权限:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.basic.lesson29" android:versioncode="1" android:versionname="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:label="@string/app_name" android:name=".MainWebView">
<intent -filter="">
<action android:name="android.intent.action.MAIN">
<category android:name="android.intent.category.LAUNCHER">
</category></action></intent>
</activity>
</application>
<uses -sdk="" android:minsdkversion="8">
<uses -permission="" android:name="android.permission.INTERNET">
</uses></uses></manifest> |
3、在res/layout/main.xml中放置一个输入框,一个按钮和一个WebView:
4、在Activity文件的OnCreate方法中默认载入一个百度页面,点击按钮时载入预设的网址http://android.yaohuiji.com :
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| package android.basic.lesson29;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
public class MainWebView extends Activity {
WebView mWebView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//定义UI组件
mWebView = (WebView) findViewById(R.id.WebView01);
Button b1 = (Button) findViewById(R.id.Button01);
final EditText et = (EditText) findViewById(R.id.EditText01);
//得到WebSetting对象,设置支持Javascript的参数
mWebView.getSettings().setJavaScriptEnabled(true);
//载入URL
mWebView.loadUrl("http://www.baidu.com");
//使页面获得焦点
mWebView.requestFocus();
//给按钮绑定单击监听器
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//访问编辑框中的网址
mWebView.loadUrl(et.getText().toString());
}
});
}
} |
5、运行程序,查看效果:
点击Go按钮,可以看到本博客出现,不过没有经过任何缩放处理,在接下里的例子我们继续研究,如何做更多的控制。
二、补充一点基础知识:关于WebSettings
1、先看一下WebView的继承关系,可以看到它不是在 android.widget包中,而是在android.webkit包中。
2、WebSettings : WebView组件有一个辅助类叫WebSettings,它管理WebView的设置状态。该对象可以通过WebView.getSettings()方法获得。下面举几个例子来说明WebSettings的用法:
//得到WebSettings对象,设置支持Javascript的参数
mWebView.getSettings().setJavaScriptEnabled(true);
//设置可以支持缩放
mWebView.getSettings().setSupportZoom(true);
//设置默认缩放方式尺寸是far
mWebView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
//设置出现缩放工具
mWebView.getSettings().setBuiltInZoomControls(true);
三、加载assets目录下的本地网页
WebView调用assets目录下的本地网页和图片等资源非常方便,使用形如
wv.loadUrl(“file:///android_asset/html/test1.html”);
的调用方法即可,代码在第四段落里。
在test1中点击链接也可以跳转到test2
四、使用 LoadData 方法加载内容
可以在Java文件中或者XML文件中定义HTML的片段,也可以在assets目录中存放HTML文件,然后使用LoadData加载其中的内容,展示出来。下面我们使用第三部分的网页来演示一下如何使用LoadData方法,并且看看他们之间的区别。
1、新建项目Lesson29_WebView2
2、新建2个Html文件在assets/html下,内容略去,res/layout/main.xml的内容也略去了,相信对你来说已经不成问题。
3、MainWebView2.java 的内容如下:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| package android.basic.lesson29;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.util.ByteArrayBuffer;
import org.apache.http.util.EncodingUtils;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
public class MainWebView2 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//定义UI组件
Button b1 = (Button) findViewById(R.id.Button01);
Button b2 = (Button) findViewById(R.id.Button02);
final WebView wv = (WebView) findViewById(R.id.WebView01);
//定义并绑定按钮单击监听器
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//加载URL assets目录下的内容可以用 "file:///android_asset" 前缀
wv.loadUrl("file:///android_asset/html/test1.html");
}
});
//定义并绑定按钮单击监听器
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data = "";
try {
// 读取assets目录下的文件需要用到AssetManager对象的Open方法打开文件
InputStream is = getAssets().open("html/test2.html");
// loadData()方法需要的是一个字符串数据所以我们需要把文件转成字符串
ByteArrayBuffer baf = new ByteArrayBuffer(500);
int count = 0;
while ((count = is.read()) != -1) {
baf.append(count);
}
data = EncodingUtils.getString(baf.toByteArray(), "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
// 下面两种方法都可以加载成功
wv.loadData(data, "text/html", "utf-8");
// wv.loadDataWithBaseURL("", data, "text/html", "utf-8", "");
}
});
}
} |
4、运行程序单击第二个按钮,效果如下:
对比上面的例子,我们可以看到两个明显的区别,其一,图片没加载出来,其二链接失效,点击后无法加载test1.html 。
五、两个和WebView相关的重要对象:WebChromeClient 和 WebViewClient
和WebView相关的辅助对象,除了WebSettings以外还有WebChromeClient和WebViewClient。
接下来的这个例子内容比较丰富,虽然注释比较清晰,但是您一次消化起来还是比较困难的,因此您需要的是一点点耐心,多看几遍,最重要的是自己至少敲代码敲一遍。
1、在上面的例子中继续增加内容,增加 test3.html 的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<script type="text/JavaScript">
function alertFuction(){
var a=1;
var b=2
alert(a+b);
}
function confirmFuction(){
confirm("你确定要删除吗?")
}
</script>
对话框测试
<input onclick="alertFuction()" value="提醒对话框" type="button">
<input onclick="confirmFuction()" value="选择对话框" type="button">
<a href="test1.html">上一页</a> |
2、MainWebView3.java的内容,请注意注释内容:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
| package android.basic.lesson29;
import java.io.FileOutputStream;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;
public class MainWebView3 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 定义UI组件
Button b1 = (Button) findViewById(R.id.Button01);
Button b2 = (Button) findViewById(R.id.Button02);
Button b3 = (Button) findViewById(R.id.Button03);
final WebView wv = (WebView) findViewById(R.id.WebView01);
// 覆盖默认后退按钮的作用,替换成WebView里的查看历史页面
wv.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && wv.canGoBack()) {
wv.goBack();
return true;
}
}
return false;
}
});
// 设置支持Javascript
wv.getSettings().setJavaScriptEnabled(true);
// 定义并绑定按钮单击监听器
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 加载URL assets目录下的内容可以用 "file:///android_asset" 前缀
wv.loadUrl("file:///android_asset/html/test1.html");
}
});
// 定义并绑定按钮单击监听器
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 加载URL assets目录下的内容可以用 "file:///android_asset" 前缀
wv.loadUrl("file:///android_asset/html/test3.html");
}
});
// 定义并绑定按钮单击监听器
b3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Picture pic = wv.capturePicture();
int width = pic.getWidth();
int height = pic.getHeight();
if (width > 0 && height > 0) {
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
pic.draw(canvas);
try {
String fileName = "sdcard/" + System.currentTimeMillis() + ".png";
FileOutputStream fos = new FileOutputStream(fileName);
if (fos != null) {
bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
}
Toast.makeText(getApplicationContext(), "截图成功,文件名是:" + fileName, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
// 创建WebViewClient对象
WebViewClient wvc = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Toast.makeText(getApplicationContext(), "WebViewClient.shouldOverrideUrlLoading", Toast.LENGTH_SHORT)
.show();
// 使用自己的WebView组件来响应Url加载事件,而不是使用默认浏览器器加载页面
wv.loadUrl(url);
// 记得消耗掉这个事件。给不知道的朋友再解释一下,Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Toast.makeText(getApplicationContext(), "WebViewClient.onPageStarted", Toast.LENGTH_SHORT).show();
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
Toast.makeText(getApplicationContext(), "WebViewClient.onPageFinished", Toast.LENGTH_SHORT).show();
super.onPageFinished(view, url);
}
@Override
public void onLoadResource(WebView view, String url) {
Toast.makeText(getApplicationContext(), "WebViewClient.onLoadResource", Toast.LENGTH_SHORT).show();
super.onLoadResource(view, url);
}
};
// 设置WebViewClient对象
wv.setWebViewClient(wvc);
// 创建WebViewChromeClient
WebChromeClient wvcc = new WebChromeClient() {
// 处理Alert事件
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
// 构建一个Builder来显示网页中的alert对话框
Builder builder = new Builder(MainWebView3.this);
builder.setTitle("计算1+2的值");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
builder.setCancelable(false);
builder.create();
builder.show();
return true;
}
@Override
public void onReceivedTitle(WebView view, String title) {
MainWebView3.this.setTitle("可以用onReceivedTitle()方法修改网页标题");
super.onReceivedTitle(view, title);
}
// 处理Confirm事件
@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
Builder builder = new Builder(MainWebView3.this);
builder.setTitle("删除确认");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
});
builder.setCancelable(false);
builder.create();
builder.show();
return true;
}
// 处理提示事件
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
JsPromptResult result) {
// 看看默认的效果
return super.onJsPrompt(view, url, message, defaultValue, result);
}
};
// 设置setWebChromeClient对象
wv.setWebChromeClient(wvcc);
}
} |
3、运行程序,查看结果:
启动起来时的画面
点击第一个按钮,我们可以看到WebViewClient对象中定义的方法的确被调用了。
点击第二个按钮,我们看到加载的网页中有两个按钮,我们知道默认情况下Android会直接忽略掉由javascript弄出来的alert等弹出信息,除非我们在WebChromeClient中覆盖onJsAlert()方法和onJsConfirm()方法,让我们分别点击它们看看效果。
接下来我们再页面中跳转几次后,使用后退按钮,查看我们是否屏蔽了Activity默认的行为,结果当然是屏蔽了^_^,这一段代码没有留意的同学回去在看一下吧。
接下来我们把页面切换到这一个网页:
然后我们按下第三个保存图片的按钮,不出意外的话我们截取到了该页的完整图片,并把它保存到了sdcard中了,我在这里展示一下我截取的效果给你看,别被它清晰的效果吓住就行^_^
好了,因为篇幅关系,我们关于WebView的功能也只能介绍到这里,关于WebView的其它功能我们在接下来的项目中会涉及到,到时候我们再一起学习,本讲就到这里吧,各位下次再见。