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.

View滑动之scrollTo/scrollBy

点击按钮【SCROLL TO】调用layout.scrollTo(100,100);即向左运动100px,向上运动100px;

点击按钮【SCROLL BY】调用layout.scrollTo(100,100);即向左运动100px,向上运动100px;

最终的效果如下。

View滑动之scrollTo/scrollBy