在Android开发过程中,会遇到需要显示网页的需求,或者需要用webview控件来达到某个效果。我这段时间在做CSDN博客的客户端,使用webview来显示博文内容,一是因为解析博文内容再适配比较麻烦,并且效果很不理想,后来想到直接用webview来显示,将博文原汁原味的呈现出来。
webview使用起来比较容易,但是想要达到比较理想的效果还需要很多摸索。我做的CSDNBlog客户端,现在基本可以使用,已经在进行版本迭代了,但是博文的webview显示效果依然不太满意,主要是因为图片的缩放问题。接下来就看看代码:
<pre name="code" class="java"> webView = (WebView) findViewById(R.id.article_content);
webView.setWebViewClient(new MyWebViewClient());
webView.getSettings().setDefaultTextEncodingName("utf-8");
webView.getSettings().setAppCacheEnabled(true);// 设置启动缓存
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
boolean isLoadImg = CSDNPreferences.getPreferenceSetting(this, getString(R.string.pre_key_loadImg), true);
Log.i(TAG, "isLoadImg=" + isLoadImg);
webView.getSettings().setLoadsImagesAutomatically(isLoadImg);
webView.getSettings().setBlockNetworkImage(true);//拦截图片的加载,网页加载完成后再去除拦截
// webView.getSettings().setJavaScriptEnabled(true);
// webView.getSettings().setDisplayZoomControls(true);// 设置显示缩放按钮
// webView.getSettings().setSupportZoom(true); // 支持缩放
// webView.getSettings().setBuiltInZoomControls(true);
//方法一:
// webView.getSettings().setUseWideViewPort(true);//让webview读取网页设置的viewport,pc版网页
// webView.getSettings().setLoadWithOverviewMode(true);
//方法二:
webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);//适应内容大小
// webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);//适应屏幕,内容将自动缩放
webview的使用主要是其setting的配置,一些常用的方法注释写的比较清楚了。
写的博客已经是可以离线查看的,所以不需要启用缓存,每次打开新的博文时,已经把获取的网页源码截取出文章正文内容存储在数据库中了。
目前遗留的问题就是图片的缩放:打开网页时,字体显示的还好,只是图片显示太大了,如果图片的宽度大于屏幕的宽度,webview就可以横向滑动,这样的体验不太好,并且给用户的感觉很耗流量。在网上查找解决办法,得到代码里提示的两种方法(大家推荐的其实还有一种方法),第一种方法中,webview会按照pc网页设置的viewport属性进行加载网页。
<meta name="viewport" content="width=device-width" >
如果有上面这样的设置,就可以适配到移动设备上,如果没有,就会默认显示pc版式的网页。
第二种方法,如注释写的一样,NARROW_COLUMNS内容不变,会根据屏幕宽度自动换行;而SINGLE_COLUMN则会让更加内容的宽度,缩放内容的大小,这样的效果就是网页被缩小到甚至文字都看不到了。
第三种方法我还没有尝试过,就是根据不同的dpi,让网页进行相应的缩放。感觉是不能解决问题的,具体效果还是得试试。
其实我想通过修改网页源码来更改图片的标签的属性,把图片的宽度设置为屏幕的宽度,正准备尝试这种办法。
需要复写一个客户端类:
/**
* 继承WebViewClient
*/
class MyWebViewClient extends WebViewClient {
//重写shouldOverrideUrlLoading方法,使点击链接后不使用其他的浏览器打开。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
progressBar.setVisibility(View.VISIBLE);
String bloger = Constants.DEFAULT_BLOG_USER_ID;
Pattern pattern = null;
System.out.println(url);
if (url.matches(Constants.DEF_STR_REGEX.REGEX_DETAILS)) {//链接为CSDN博客内容
new MainTask().execute(url);
return true;
} else if (url.matches(Constants.DEF_STR_REGEX.REGEX_BLOG)) {//博客主页
pattern = Pattern.compile(Constants.DEF_STR_REGEX.REGEX_BLOG);
} else if (url.matches(Constants.DEF_STR_REGEX.REGEX_CATEGORY)//博客列表或者分类
|| url.matches(Constants.DEF_STR_REGEX.REGEX_BLOGLIST)) {
pattern = Pattern.compile(Constants.DEF_STR_REGEX.REGEX_LIST);
} else {
return false;//让系统处理该链接请求
}
Matcher matcher = pattern.matcher(url);
if (matcher.find()) {
bloger = matcher.group(1);
}
CSDNApplication.getInstance().setCurrentBlogerID(bloger);
mDB.saveBloger(bloger);
Intent intent = new Intent();
intent.setClass(BlogContentActivity.this, MainTabActivity.class);
intent.putExtra(getString(R.string.app_name), Constants.DEF_BLOG_TYPE.BLOGERBLOG);
startActivity(intent);
BlogContentActivity.this.finish();
//如果不需要其他对点击链接事件的处理返回true,否则返回false
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
<span style="white-space:pre"> </span>webView.getSettings().setBlockNetworkImage(false);//去除图片拦截,继续加载图片
super.onPageFinished(view, url);
Log.i(TAG, "onPageFinished");
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Log.i(TAG, "onReceivedError");
//这里进行无网络或错误处理,具体可以根据errorCode的值进行判断,做跟详细的处理。
}
}
在这里把代码都贴过来了,主要是对webview网页内部的链接进行的处理,如果是CSDN的博文,就直接显示在当前页,如果是博文列表就退出到上一个界面进行显示,如果是其他的网页链接就直接通过android默认的打开方式处理。
webview的其他使用技巧,等到大神前来指点。
此致