WebView加载HTML内容监听

最近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操作符时,记得取消定时器


如果小伙伴发现书写中出现错误,或者有更好的办法解决此问题,欢迎留言和私信。

发布了26 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/xyl826/article/details/105008486