美文网首页
SwipeRefreshLayout与WebView内部子可滚动

SwipeRefreshLayout与WebView内部子可滚动

作者: 鹅鹅鹅_ | 来源:发表于2018-12-27 14:28 被阅读0次

问题参见下图(图片来自于网络:))


20170901174631281.gif

下图是我的页面,分为3个div,三个div的高度加起来是100%占据整个webview页面。而最下面的第三个div是一个可滚动的div(overflow: "auto")。往上滑动时没问题的,但是往下滑动就会出现上面gif中的问题。


image.png
网上有如下解决方案,但是针对这个案例是无效的,因为本案例中webView.getScrollY始终为0(三个div构成了整个webview页面,自始至终这三个div位置是不会变化的,是固定的)
// 设置子视图是否允许滚动到顶部
    refreshLayout.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() {
       @Override
       public boolean canChildScrollUp(SwipeRefreshLayout parent, @Nullable View child) {
           return webView.getScrollY() > 0;
       }
    });

所以问题在于如何监听webview页面内子布局的滚动,以子布局的滚动来控制刷新动作。
可以利用webview的evaluateJavascript方法来监听特定元素,第一个参数script用于执行一段js脚本以获取指定元素的指定属性比如div的height,第二个参数resultCallback是一个回调函数,当取到第一个参数指定的属性时就会执行调用。

public void evaluateJavascript(String script, ValueCallback<String> resultCallback)

所以解决方案很明了了。只需要利用evaluateJavascript来监听可滚动的div的scrollTop值,当其为0时表示在顶端,此时下拉可以刷新。否则禁止下拉刷新。注意,这里需要和前端商量约定统一的要监听的元素的id,即下面的inner_scroll_box。

webView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {

                    case MotionEvent.ACTION_MOVE:
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            webView.evaluateJavascript("document.getElementById(\"inner_scroll_box\").scrollTop", new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {
                                    if (!TextUtils.isEmpty(value) && !"null".equals(value)) {
                                        if (Integer.parseInt(value) == 0) {
                                            refreshLayout.setEnabled(true);
                                        } else {
                                            refreshLayout.setEnabled(false);
                                        }
                                    }
                                }
                            });
                         }
                         break;
              }
}

对于没有id的React组件,比如antd mobile组件Picker,就需要添加一个隐藏的div,然后根据Picker的状态的改变来改变div的height,最后就可以在android端根据div的高度来决定是否可以下拉刷新了。


Picker

添加id为type_picker的隐藏div,在onVisibleChange中根据Picker列表的隐藏状态来改变div的高度。

<div>
                <Picker data={vms} cols={1} title={"资金类型"} value={this.state.value} extra={v2label[this.state.value]}
                    onChange={v => {if (v === this.state.value) {this.handleChange(v2type[v]);this.setState({ value: v })}}}
                    onVisibleChange={v => {if (v===true) {document.getElementById('type_picker').style.height="1px"} else {document.getElementById('type_picker').style.height="0px"}}}
                >
                    <CustomPickerButton/>
                </Picker>
                {/*添加此div是为了与android端进行特殊操作,让android端知道Picker隐藏状态*/}
                <div id={"type_picker"} style={{visibility: "none", height: 0}}></div>
            </div>

在android端根据id为type_picker的div的高度来决定是否可以下拉刷新。

webView.evaluateJavascript("document.getElementById(\"type_picker\").style.height", new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {
                                    if (!TextUtils.isEmpty(value) && !"null".equals(value)) {
                                        if (!"0px".equals(value.replace("\"", ""))) {
                                            refreshLayout.setEnabled(false);
                                        } else {
                                            refreshLayout.setEnabled(true);
                                        }
                                    }
                                }
                            });

相关文章

网友评论

      本文标题:SwipeRefreshLayout与WebView内部子可滚动

      本文链接:https://www.haomeiwen.com/subject/weyrlqtx.html