最近Android开发时,在WebView加载网页的时候遇到一个问题,感觉很有趣,记录一下,如果有更好方案的朋友评论和私信都可以,共同学习。
需求:
手机某个页面加载一个网页,当网页内容滑动到底部(完全展示)时,底部的按钮才变为可点击状态
方案:
给Webview设置监听,当WebView滑动时,通过WebView控件的高度、滑动的距离、WebView中html内容的高度、
来确定内容是否显示完毕,同时更新底部按钮的状态
话不多说,上代码:(这里只是添加滑动监听,其余的WebView配置不要忘记添加)
private static final float ALLOW_DEVIATION_VALUE = 10f;
View.OnScrollChangeListener onScrollChangeListener = new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
float slideDeviation = (mWebView.getContentHeight() * mWebView.getScale()) - (mWebView.getHeight() + mWebView.getScrollY());
if (slideDeviation <= ALLOW_DEVIATION_VALUE) {
mTestBtn.setEnabled(true);
mTestBtn.setTextColor(getResources().getColor(R.color.green));
}
}
};
mWebView.setOnScrollChangeListener(onScrollChangeListener);
mWebView.loadUrl(mUrl);
参数:
getContentHeight : 加载的html内容高度
getScale: 内容缩放比例
getHeight : 控件高度
getScrollY:手指向上/向下滑动的距离
ALLOW_DEVIATION_VALUE: 允许误差值
小功告成,么么哒!
带来的问题:
上述的解决方案,有问题吗?看起来并没有问题,但是考虑的场景有遗漏,比如:
场景1:
html内容较少,手机屏幕1页就显示完了,WebView并没有触发滑动监听,此时html内容显示完整,但此时你的按钮状态就没有更新,按钮自然就无法点击了(后果,后果,你懂的,面对疾风吧......)
场景2:
使用平板设备,屏幕本身就很大,html内容较多但1页就显示完了,同样也是没有触发滑动监听
综上所述:两种情况都是没有触发滑动监听,此时就无法监测WebView内容来更新按钮状态了
如何解决:
这时候,大部分人都知道怎么做了,这样做:
当网页加载完毕时,检测WebView内容高度,然后去更新按钮状态
没错,大部分人都想到了,在
WebViewClient--->onPageFinished 方法中进行 WebView内容检测,检查是否已经显示完毕;
但是,What ? What ? 代码运行,Fuck ! 发现html没有显示完的时候,按钮状态也更新了,也可以点击
经过一番打印,发现 mWebView.getContentHeight 的值为 0 ;
这是因为
onPageFinished
回调意味着WebView已完成从网络读取字节的操作。此时,onPageFinished
页面可能甚至没有被解析。
也就是说,我们获取WebView内容高度的时机太早了。
但是吧,不能就这么算了,我们获取时机太早了,那就延迟获取,延迟的时间不能太长,也不能太短;(太短没效果,太长用户发现会觉得奇奇怪怪的)
方案:每间隔500毫秒,获取一次内容高度,不为0的话就停止获取高度的操作,直接进行计算,更新状态;
这不,RxJava的延迟操作符安排一波,代码如下:
//Rxutil是自己封装的工具类,包含对interval操作符的封装
//ICallBack 是RxUtil工具类中的一个接口,接口内一个方法
//每隔500毫秒获取一次WebView内容的高度
disposable = RxUtil.interval(0, 500, new RxUtil.ICallBack() {
@Override
public void doNext(long number) {
if (mWebView.getContentHeight() != 0) {
//WebView内容高度检查
//取消定时器
}
}
});
思路整理:
WebView加载html时,当需要对内容进行监听,并且根据内容显示是否完整,更新页面按钮状态时,
第一步:要对 WebView设置滑动监听,根据 内容高度、控件高度、滑动距离,来计算是否完全显示,实时更新其按钮状态
第二步:其次,要考虑1页显示完毕的情况,避免滑动监听不生效的问题,在html加载完毕后,延时获取内容高度(立即获取有时候获取内容高度为0),
第三步:当获取内容高度不为0时,再去根据 内容高度、控件高度、滑动距离,来计算是否完全显示,实时更新其按钮状态 (此操作仍在onFinishPage方法中进行)
注意点:使用RxJava的interval操作符时,记得取消定时器
如果小伙伴发现书写中出现错误,或者有更好的办法解决此问题,欢迎留言和私信。