Android

Java安卓学习总结(三十四)

第三十章 网页浏览

有关实现网页浏览的两种方式

隐式Intent

这种方法直接将URL抛给外部的浏览器来处理:

public void onClick(View view) {
           Intent i=new Intent(Intent.ACTION_VIEW,mGalleryItem.getPhotoPageUri());
            startActivity(i);

        }

使用WebView

这种方法将这些URL全都交给自己的WebView来处理,要定义这个WebView组件所处的fragment以及托管它的Activity。这些东西都是轻车熟路了,不写了。

现在针对WebView的方法进行总结:

mWebView=(WebView)view.findViewById(R.id.web_view);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl(mUri.toString());

mWebView.getSettings().setJavaScriptEnabled(true);是启用JavaScript;mWebView.setWebViewClient(new WebViewClient());用于响应WebView上的渲染事件;mWebView.loadUrl(mUri.toString());用于加载URL。

WebViewClient()的作用就是去实现例如重定向URL,响应WebView的渲染时间等等需求的类。接下来要用到一个类来优化WebView显示。

WebChromeClient

如果说上面的WebViewClient是响应渲染事件的接口,那么WebChromeClient就是用于响应那些改变浏览器中装饰元素的事件接口(包括JavaScript警告信息、网页图标、状态条加载、网页标题刷新)

下面会调用两个方法来实现状态条加载和网页标题刷新:

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 appCompatActivity=(AppCompatActivity)getActivity();
appCompatActivity.getSupportActionBar().setSubtitle(title);
}
});

public void onProgressChanged(WebView view, int newProgress)配合了视图中的有关ProgressBar,来完成状态条;onReceivedTitle直接设置Activity的状态栏子标题。

有关三种fragment处理设备旋转的方式

一开始学的是用onSaveInstanceState来存储数据,实现原理同activity的,每当设备旋转时,它会从头开始加载数据。

在处理asset时介绍了暂时保留fragment实例,这要求fragment能稍后立刻与新建立的activity完成绑定,否则自己也会消失。

上面两种都处理不了保存网页信息的需求,因此介绍了最后一种,也是死到临头的一种方式:让fragment自己处理设备配置的变更。

第三种一听上去就不靠谱,我自己写的fragment,为什么它能教我做事啊。行吧,书上说这么做资源修饰符无法工作了,而且activity/fragment自己处理了设备配置修改了,可能不会去覆盖onSaveInstanceState中存储的UI状态了。

有关挑战练习 使用后退键浏览历史网页

重难点在于怎么在activity中去获取fragment中的WebView。之前学的从fragment返回结果给activity,是利用的startActivityForResult方法,这个方法的问题在于,必须要fragment结束时才有结果返回。这可不行,这显然不行,所以我就用了回调接口的方式:

定义回调接口,并获取实例:

public class PhotoPageFragment extends VisibleFragment {
...
private getWebView mGetWebView;

public interface getWebView
{
void getWebView(WebView webView);
}
...

@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
mGetWebView = (getWebView) context;
}
}

在activity中实现接口:

@Override
public void getWebView(WebView webView) {
mWebView=webView;
}

然后要搞清楚什么时候调用这个接口方法,显然是每当一个网页加载好了之后才能将当前的WebView快照传递给activity嘛。所以重写onPageFinished方法:

mWebView.setWebViewClient(new WebViewClient()
{
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        mGetWebView.getWebView(view);
    }
});

然后就是在activity的onBackPressed方法中进行处理:

@Override
public void onBackPressed() {

if (mWebView!=null)
{
if (mWebView.canGoBack())
{
mWebView.goBack();
}
else
{
super.onBackPressed();
}
}
else
{
super.onBackPressed();
}

}

有关挑战练习 非HTTP链接支持

在做这个挑战练习之前,我先是特地地去找了一下有没有这种非http的链接。我也不知道为什么Flickr不想去推广它们的app了,反正我没找到哪里有下载或打开app的链接,我还点了很多个广告,结果都没有。

所以这次挑战练习我也不知道我写的对不对,我借鉴了这个帖子去写的,希望以后有机会能够验证一下。

mWebView.setWebViewClient(new WebViewClient()
{
    ...
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.indexOf("http")!=-1||url.indexOf("https")!=-1)
        {
            return false;
        }
        else
        {
            Uri uri=Uri.parse(url);
            Intent i=new Intent(Intent.ACTION_VIEW,uri);
            startActivity(i);
            return true;
        }
    }
});

shouldOverrideUrlLoading方法其实已经被弃用了,但是替代的新方法有版本要求(起码Lollipop),所以我就直接用旧的了。

shouldOverrideUrlLoading返回值为false时让WebViewClient处理,为true时自行解决。

发表评论