记录下最近开发中研究的带进度条的WebView 自定义类吧。
其实网上有不少这样的帖子,但是都没有一个完整的好用的例子,最关键的是,用网上的例子后有一个很明显的bug,就是遇到输入框的话没法弹出软键盘。研究了好久总算搞定了。特此记录下。
直接上源代码,关于代码的解释,个人感觉注释中已经添加的足够清楚了。
ProgressWebView
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import com.touziqu.sealily.newinvestmentgo.R;
import com.touziqu.sealily.newinvestmentgo.Utils.LogUtils;
import com.touziqu.sealily.newinvestmentgo.Utils.OnWebCallBack;
/**
* File Description: 自定义带有进度条的webview
* 继承自{@link WebView}
* Created by KAKA on 16/1/19 22:21
* 主要在{@link ProgressWebView#ProgressWebView(Context, AttributeSet, int)}中完成实例的构建
* 使用{@link ProgressWebView#ProgressWebView(Context, AttributeSet)}时要注意destyle类型的设置
*/
@SuppressWarnings("deprecation")
public class ProgressWebView extends WebView {
/**
* 进度条
*/
private ProgressBar progress_bar_;
/**
* 回调
*/
private OnWebCallBack onweb_callback_;
/**
* Description: Default Constructor
* Created by KAKA on 16/1/19 22:23
*/
public ProgressWebView(Context context) {
super(context);
}
/**
* 不能直接调用this(context, attrs,0),最后style是0的话,会导致无法响应点击动作。
* 但是如果直接把最后一位写成 com.android.internal.R.attr.webViewStyle 编译时会弹出错误提示,原因:
* You cannot access id's of com.android.internal.R at compile time, but you can access the
* defined internal resources at runtime and get the resource by name.
* You should be aware that this is slower than direct access and there is no guarantee.
*/
public ProgressWebView(Context context, AttributeSet attrs) {
this(context, attrs, Resources.getSystem().getIdentifier("webViewStyle","attr","android"));
}
/**
* Description: Copy Constructor
* Created by KAKA on 16/1/19 22:23
* isInEditMode函数的作用是去除打开XML文档时提示的错误
*/
public ProgressWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (!isInEditMode()) {
initView(context);
}
setWebViewClient(new MyWebViewClient());
setWebChromeClient(new WebChromeClient());
}
/**
* Description: 初始化界面元素
* Created by KAKA on 16/1/20 09:43
* LayoutParams中第2个参数表示的是progress_bar的高度大小
*/
private void initView(final Context context) {
progress_bar_ = new ProgressBar(context,null, android.R.attr.progressBarStyleHorizontal);
progress_bar_.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 20, 0, 0));
// 添加drawable
Drawable drawable = context.getResources().getDrawable(R.drawable.progress_bar_states);
progress_bar_.setProgressDrawable(drawable);
this.addView(progress_bar_);
}
/**
* Description: 设置webview的回调器
* Created by KAKA on 16/1/20 13:56
*/
public void setOnWebCallback(OnWebCallBack onwebcallback) {
this.onweb_callback_ = onwebcallback;
}
/**
* Description: 重写WebViewClient类,不重写的话会跳转默认浏览器
* Created by KAKA on 16/1/19 23:26
*/
public class MyWebViewClient extends WebViewClient {
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) { // Handle the
goBack() ;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
/**
* Description: 获取请求页面的URL
* Created by KAKA on 16/1/20 13:54
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (onweb_callback_ != null) {
onweb_callback_.getUrl(url);
}
}
}
/**
* Description: 重写webChromeClient类
* Created by KAKA on 16/1/19 22:40
*/
public class WebChromeClient extends android.webkit.WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
LogUtils.i("当前进度",newProgress + "%");
if (newProgress == 100) {
progress_bar_.setVisibility(GONE);
} else {
if (progress_bar_.getVisibility() == GONE) {
progress_bar_.setVisibility(VISIBLE);
}
progress_bar_.setProgress(newProgress);
}
super.onProgressChanged(view,newProgress);
}
/**
* Description: 获取页面的标题
* Created by KAKA on 16/1/20 13:54
*/
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view,title);
if (onweb_callback_ != null ) {
onweb_callback_.getTitle(title);
}
}
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
LayoutParams lp = (LayoutParams) progress_bar_.getLayoutParams();
lp.x = l;
lp.y = t;
progress_bar_.setLayoutParams(lp);
super.onScrollChanged(l, t, oldl, oldt);
}
}
两个要点:
1. 在构造函数中 不能直接调用this(context, attrs,0),最后style是0的话,会导致无法响应点击动作。同时也不能直接写成 com.android.internal.R.attr.webview ,具体的原因注释里面已经写的很清楚了
2. 在initView之前先判断了一个情况: isInEditMode(), 加入这个函数是不会在XML文件打开时弹出一个冗长的错误。其实不加这个判断条件也可以,但是作为重度强迫症患者,必须把XML文件上烦人的提示给去掉才行。。。
接下来看一下进度条的drawable文件
progress_bar_states.XML
<?xml version="1.0" encoding="utf-8"?>
<!--WebView顶端的进度条的样式-->
<!--layer-list 层叠样式-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dp" />
<gradient
android:angle="270"
android:centerColor="#E3E3E3"
android:endColor="#E6E6E6"
android:startColor="#C8C8C8" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp" />
<gradient
android:centerColor="#4AEA2F"
android:endColor="#31CE15"
android:startColor="#5FEC46" />
</shape>
</clip>
</item>
</layer-list>
最后对我们自定义的progresswebview的调用就像普通的web view一样了。
例如在某个activity中用下面的方式来调用(XML文件我就不列出了,非常简单):
web_view_ = (ProgressWebView) view.findViewById(R.id.web_view);
web_view_.setOnWebCallback(new OnWebCallBack() { // 设置回调
@Override
public void getTitle(String title) {
LogUtils.i("当前页面的标题", title);
}
@Override
public void getUrl(String url) {
LogUtils.i("访问页面的url是", url);
}
});
web_view_.loadUrl("http://m.baidu.com");
web_view_.getSettings().setJavaScriptEnabled(true);
回调的作用你可以看到当前访问的URL的页面标题和地址。
最后如果你的页面有用到JS,一定要设置JS为enable。