在View的源码中,mScrollX和mScrollY是视图在X轴和Y轴的偏移量。接下来再看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;
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
invalidate();
}
}
}
/**
* Move 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 amount of pixels to scroll by horizontally
* @param y the amount of pixels to scroll by vertically
*/
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
从源码中可以看到,scrollBy()的内部其实是调用了scrollTo()。在scrollTo()中,调用了onScrollChanged()和invalidate()。
onScrollChanged()的作用就是告诉系统(可以理解为Android框架),这个View的scrollTo()或scrollBy()曾经被调用过;而invalidate()是告诉系统,这个View需要被重新绘制。
区别
public void scrollTo(int x, int y) —— x,y 为偏移量;
说明:始终都是相对于View最初的位置,偏移(x,y)个单位像素;
public void **scrollBy **(int x, int y) ——x,y为偏移量
说明: 相对于View当前偏移到的位置,继续偏移(x,y)个单位像素;
备注: 这两个方法作用只是View中的内容位置发生偏移,并非View本身。偏移量计算方式就是原点(x, y)到目标点(x1, y1)的距离,即(x ,y) - (x1,y1) = ( x-x1,y-y1)。
下面举个例子。
假设一个控件TextView,称之为tv。如果想把tv从(0, 0)移动到(100, 100),{这里说的(0, 0)和(100, 100),指的是tv左上角的坐标}。那偏移量 代入得 (0 , 0) - (100, 100) = (-100, -100)。 只需要调用tv.scrollTo(-100, -100)就可以了,此时tv的左上角坐标为(100,100)。备注 :此时参照物原始坐标(0, 0)。执行多次tv.scrollTo(-100, -100)方法,内容左上角坐标依然为(100,100)。
scrollBy()是有一定的区别的。scrollBy()的参照物是当前位置坐标。如tv调用了scrollTo(-100, -100),此时tv左上角的坐标是(100, 100),这时再调用scrollBy(-20, -20),此时tv的左上角就被绘制到了(120, 120)这个位置。
测试遗留问题
经测试,如果是View,多次调用scrollTo/scrollBy,与上面结论一致, 但是如果是自定义View 继承不是View,而是l ayout (如 relativeLayout),多次调用这个自定义View的scrollTo/scrollBy,发现 自定义 View中的自控件位置只发生了一次改变,scrollBy作用与scrollTo作用一致,目前还是搞不怎么回事,欢迎留言