一、 必须牢记的知识点
scrollTo/scrollBy来实现的滑动,只是使View中的内容整体滑动,并没有滑动View的实际位置,也就是不管怎么滑动,都不会改变View的位置,这点要特别注意。如下图,黑线框代表View的位置,里面的灰色区域代表View中的整体内容。
二 、scrollTo/scrollBy易搞错的地方
View内部的两个属性mScrollX和mScrollY,分别可以通过getScrollX、getScrollY获得,但还是需要说明几点:
- 在滑动过程中,mScrollX的值总是等于View的左边缘到View内容的左边缘的水平距离(View左边缘x - View内容左边缘x),mScrollY的值总是等于View的上边缘到View内容的上边缘的竖直距离(View上边缘y - View内容上边缘y)。
- View的边缘是指View的的位置,有四个顶点组成,View内容边缘是指View中内容的边缘,具体如下所示。
- mScrollX/mScrollY单位是像素,当View的左边缘在View内容左边缘左边时,mScrollX为负数,反之则为正数;View上边缘在View内容上边缘上边时mScrollY为负数,反之则为正数。换句话说:从左向右滑动时mScrollX为负数,反之则为正数;从上向下滑动时mScrollY为负数,反之则为正数,请结合1的结论理解;
三、scrollTo/scrollBy实现的滑动
首先来看一段源码
/**
* Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
从源码我们可以看出:
- scrollBy实际上也是调用了scrollTo
- scrollTo使基于所传参数的绝对滑动(比如:当前坐标是(1,1)所传参数x:2,y:2,最终会滑动到(2,2))
- scrollBy使基于当前位置的相对滑动(比如:当前坐标是(1,1)所传参数x:2,y:2,最终会滑动到(1+2,1+2))