canScrollVertically和scrollBy的使用问题

最近项目使用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

}

```

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容