Contents
  1. 1. ProgressWebView.java
  2. 2. progress_bar_states.XML
  3. 3. 调用ProgressWebView

记录下最近开发中研究的带进度条的WebView 自定义类吧。
其实网上有不少这样的帖子,但是都没有一个完整的好用的例子,最关键的是,用网上的例子后有一个很明显的bug:就是遇到输入框的话没法弹出软键盘。研究了好久总算搞定了,特此记录下。

直接上源代码,关于代码的解释,个人感觉注释中已经添加的足够清楚了。

注意:我省去了部分import的内容,因为是和我的工程命名相关的。

ProgressWebView.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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;

/**
* 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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

最后对我们自定义的progresswebview的调用就像普通的webview一样了。
例如在某个activity中用下面的方式来调用(XML文件我就不列出了,非常简单):

1
2
3
4
5
6
7
8
9
10
11
12
13
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);

web_view_ 是我们定义的private 成员变量,然后它对应这XML文件中id是web_view的progressWebView控件。
回调的作用你可以看到当前访问的URL的页面标题和地址。
最后如果你的页面有用到JS,一定要设置JS为Enable

Contents
  1. 1. ProgressWebView.java
  2. 2. progress_bar_states.XML
  3. 3. 调用ProgressWebView