View滑动之scrollTo/scrollBy
Android设备上组件的滑动是所有应用的标配,不管是向上滑动加载更多数据,还是下拉刷新数据等等操作,他们的基础都是滑动。在原声组件的滑动中,scrollTo/scrollBy是其中一种比较重要的,也是比较典型的一种滑动方式。即便是用到Scroller编写自定义的滑动效果时,也是以scrollTo/scrollBy为基础的。
本文主要介绍下scrollTo/scrollBy两个方法的基本操作和需要注意的地方,为更深层次认识组件的滑动提供基础性帮助。
首先看一下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();
}
}
}
/**
* 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
方法则是实现了基于所传参数的绝对滑动。
下面将具体解析一下这两个方法的参数说明、方向情况、异同点以及在调用中需要注意的地方。
1)调用方法的主体和实际运动的主体
大家可能有些困惑,加入一个视图layout中含有一个子视图view。其实当调用layout.scrollTo(x,y)或者layout.scrollBy(x,y)时
运动的其实是layout中的子视图view。
这一点特别重要。后面将会以小demo的形式予以展示。
2)参数说明
scrollTo(int x, int y) /scrollBy(int x, int y)两个方法中,每个方法都需要传递两个int类型的参数。其中,第一个参数代表的是
在横向运动的大小,第二个参数代表在纵向运动的大。需要注意的是,他们的单位是像素px,而不是dp。
3)方向说明
scrollTo(int x, int y) /scrollBy(int x, int y)中参数的正负与方向的关系是:x为正时向左运动,x为负时向右运动;y为正时向
上运动,y为负时向下运动。这个听起来有点奇怪,因为在手机屏幕上都是横向从左向右为正,纵向从上向下为正。大家要是深
入了解滑动到实质就好。因为第一个问题已经说过,layout本身是不动的,真正运动的是layout中的子视图view,运动的距离大
小实际上是:x代表view左边缘与layout左边缘的相对运动距离,(view左边缘-layout左边缘)的正负则是代表横向运动的正
负,(view上边缘-layout上边缘)的正负代表纵向运动的正负。
4)运动的次数
scrollTo(int x, int y)调用时,因为是绝对运动,所以在多次调用后也只能运动一次。原因是view相对于其原来的位置进行一次
绝对运动这一点可以从其具体的代码实现中找到答案。而scrollBy(int x, int y)则是相对运动,调用N次的话,则会相对于原先的位置
进行N次运动,每一次运动都会相对于前一个位置移动(x,y)个像素。
最后,举一个简单的例子。在一个布局layout中添加3个子视图viewGreen、viewRed、viewBlue.
点击按钮【SCROLL TO】调用layout.scrollTo(100,100);即向左运动100px,向上运动100px;
点击按钮【SCROLL BY】调用layout.scrollTo(100,100);即向左运动100px,向上运动100px;
最终的效果如下。