最近项目使用CoordinatorLayout + Webview实现文章详情页上拉折叠头部效果,由于Webview并不支持app:layout_behavior,于是在Webview外套了一层NestScrollView, 由NestScrollView支持app:layout_behavior,然后重写NestScrollView的dispatchNestedScroll来控制Wevview的滚动,一开始的实现是
```
val canScroll =mWebView.canScrollVertically(dy)
if (canScroll) {
...
mWebView.scrollBy(dxUnconsumed, dy)
...
return true
}
```
然后发现往上滚时,mWebView顶部的一些内容滚不下来了,而且canScrollVertically返回false
后来通过一番研究,发现这是View的一个坑(也算是View的一个bug)
View内部有个变量mScrollY记录当前滚动距离,当scrollBy(dxUnconsumed, dy)中的dy+mScrollY < 0 时,scrollBy不会进行任何实际滚动,但同时它却会把mScrollY设为为dy+mScrollY
这就导致之后怎么滚都滚不下来(此时dy < 0)
因为canScrollVertically()的实现是:
```
public boolean canScrollVertically(int direction) {
final int offset = computeVerticalScrollOffset();
final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
if (range ==0)return false;
if (direction <0) {
return offset >0;
}else {
return offset < range -1;
}
}
protected int computeVerticalScrollOffset() {
return mScrollY;
}
```
当最后一次滚动的dy < -mScrollY 时, mScrollY = dy+mScrollY, mScrollY变为负数,导致之后的往上滚时canScrollVertically都是返回false。
问题解决的方法是实现dispatchNestedScroll改为以下代码
```
val canScroll =mWebView.canScrollVertically(dy)
if (canScroll) {
...
if (dy < 0) {
dy = -min(-dy, mWebView.computeVerticalScrollOffset())
mWebView.view.scrollBy(dxUnconsumed, dy)
return true
}
...
return true
}
```
网友评论