Android编程权威指南(第二版)学习笔记(二十八)—— 第28章 网页浏览
本章主要讲的是使用 WebView 在应用内浏览网页
GitHub 地址:
完成第28章,未完成挑战
完成第28章挑战
1. WebView
如果不使用 WebView,我们可以使用隐式 intent,也就是用独立的浏览器打开一个网页。但是我们通常只想在 activity 中显示网页内容而不是打开浏览器:或许是想显示自己生成的 HTML,或许是想以某种方式限制用户使用浏览器。对于大多数需要帮助文档的应用,普遍做法是以网页的形式提供帮助文档,这样会方便后期的更新与维护。打开浏览器查看帮助文档,既不专业,又妨碍应用行为的定制,同时也无法将网页整合进自己的用户界面。
1.1 WebView 的使用
和其他的 View 一样,在 fragment 的布局文件中声明之后,在 fragment 中获取实例,然后进行一番设置:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/fragment_photo_page_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
public class PhotoPageFragment extends VisibleFragment {
private static final String ARG_URI = "photo_page_url";
private Uri mUri;
private WebView mWebView;
………………
// 在这里防止 Lint 警告 JavaScript 被启用
@SuppressLint("SetJavaScriptEnabled")
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_photo_page, container, false);
// 首先获取实例
mWebView = (WebView) v.findViewById(R.id.fragment_photo_page_web_view);
// 然后将 JavaScript 设置为启用
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
// 这个方法决定 url 在哪里处理,返回 false 代表让 WebView 去加载
// 其实该方法默认返回的就是 false
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
mWebView.loadUrl(mUri.toString());
return v;
}
}
可以看到,WebClient 是一个关键,如果不重写该方法,WebView 可能不会加载这个 url
1.2 使用 WebChromeClient 优化 WebView 显示
WebViewClient 主要帮助 WebView 处理各种通知、请求事件,而 WebChromeClient 主要辅助 WebView 处理 Javascript 的对话框、网站图标、网站 title、加载进度等。
我们在视图中加入 ProgressBar 放在 WebView 上方并默认隐藏,由于 WebChromeClient 返回进度值在0~100之间,所以我们要设置进度条的最大值为100。
mProgressBar.setMax(100); // WebChromeClient 进度范围就是0~100
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
mProgressBar.setVisibility(View.GONE);
} else {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(newProgress);
}
}
@Override
public void onReceivedTitle(WebView view, String title) {
AppCompatActivity activity = (AppCompatActivity) getActivity();
设置网站标题
activity.getSupportActionBar().setSubtitle(title);
}
});
1.3 处理 WebView 的设备旋转问题
尝试旋转设备屏幕,可以发现 WebView 必须重新加载网页。这是因为 WebView 包含太多的数据,无法在 onSaveInstanceState(...)方法内全部保存。所以每次设备旋转,它都必须从头开始加载网页数据。
因为 WebView 是视图层级结构的一部分,所以旋转后它肯定会销毁并重建,不能用 retainFragment 来保留。对于一些类似的类(如 VideoView),Android 文档推荐让 activity 自己处理设备配置变更。也就是说,无需销毁重建 activity,就能直接调整自己的视图以适应新的屏幕尺寸。这样,WebView 也就不必重新加载全部数据了。
<activity android:name=".PhotoPageActivity"
android:configChanges="keyboardHidden|orientation|screenSize"/>
android:configChanges 属性表明,如果因键盘开或关、屏幕方向改变、屏幕大小改变(也包括 Android 3.2之后的屏幕方向变化)而发生设备配置更改,那么 activity 应自己处理配置更改。
2. 挑战练习
2.1 使用后退键浏览历史页面
我们覆盖 Activity.onBackPressed 方法,就可以对返回键的行为进行控制,但是要获取 WebView 的实例,所以在 fragment 中加入了一个 getter。
// PhotoPageActivity.java
@Override
public void onBackPressed() {
PhotoPageFragment fragment = (PhotoPageFragment) getSupportFragmentManager()
.findFragmentById(R.id.fragment_container);
if (fragment.getWebView().canGoBack()) {
fragment.getWebView().goBack();
} else {
super.onBackPressed();
}
}
2.2 非 HTTP 链接支持
只需要修改重写的 shouldOverrideUrlLoading 方法即可。
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("https://") || url.startsWith("http://")) {
return false;
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
});
GitHub Page: kniost.github.io
简书:http://www.jianshu.com/u/723da691aa42
下一篇: 力扣题解(二)-------二分查找