SwipeRefreshLayout与WebView内部子可滚动
2018-12-27 本文已影响0人
鹅鹅鹅_
问题参见下图(图片来自于网络:))
![](https://img.haomeiwen.com/i14125002/3b6344b32504e42d.gif)
下图是我的页面,分为3个div,三个div的高度加起来是100%占据整个webview页面。而最下面的第三个div是一个可滚动的div(overflow: "auto")。往上滑动时没问题的,但是往下滑动就会出现上面gif中的问题。
![](https://img.haomeiwen.com/i14125002/8f39fdf3b3963feb.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的高度来决定是否可以下拉刷新了。
![](https://img.haomeiwen.com/i14125002/7567d126f59e16c3.png)
添加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);
}
}
}
});