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;
        }
    }
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值