scrollTo和getScrollY表象和源码结合效果更佳!

getScrollY()是自定义View中的常客,但是由于android特有的坐标系以及屏幕与View之间的复杂关系,往往是分析和看源码的难点,这里结合示意图帮助理解getScrollY,一劳永逸。

名词理解

首先我们需要了解清楚几个概念,就是我们经常看到的向上/下滚动以及上/下滑这四个名词:

!!!记住滚动和滑动在android中的含义是不同的!!!

上滑/下滑是我们手指相对于整个屏幕而言的,手指从屏幕上方滑动到下方,称为下滑,反之称为上滑。

向上/下滚动一般是View相对于屏幕而言的,我们假定下面左图中的场景:

scrollTo和getScrollY表象和源码结合效果更佳!_第1张图片

当我们说向上滚动时,意味着我们可以看到View的上半部分,所以相对于屏幕来说View整体下移,也即手指触摸点下移,可以看作是手指拉着View的内容向下移动,也即下滑,如上右图。

所以所说的向上滚动对应着下滑,而向下滚动对应着上滑。

如何理解“左正右负,上正下负”

首先需要知道,scrollTo这个方法移动的是View内容,而其位置是不变的,就像属性动画和补间动画的区别一样。

标题这句话与Android的坐标系正好相反,这就是scrollTo和getScrollY让人难以理解的地方。我们不妨先来看看这两个方法的源码实现:

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();  
        }  
    }  
}  
public final int getScrollY() {  
    return mScrollY;  
}

可以看出getScrollY方法返回的正是在scrollTo中设置的y,也就是当前View的内容相对于当前View的y方向偏移量。在测试中我们可以看到:

当y>0时,也就是getScrollY>0,这时候View的内容相对于其View容器位于左侧;
当y<0时,也就是getScrollY<0,这时候View的内容相对于其View容器位于右侧;

参见下图:

这里写图片描述

根据以上特点,我们可以将getScrollY的返回值简单的记忆成:View容器左上顶点的y值减去View的内容左上顶点的y值。

如果还是不太理解可以看下图:

scrollTo和getScrollY表象和源码结合效果更佳!_第2张图片

我们可以将屏幕看作静止不动的,而View的内容是在一条长长的画布上,其View容器假定为屏幕位置且固定不动,初始状态时View内容位于View的最左边,也就是getScrollX返回0,当我们调用scrollTo(-100, 0)时,也就是getScrollX返回-100,按照我们上面说的,也就是

y(容器) - y(内容)= -100;

所以内容的左上角比容器的左上角,其横坐标要向右偏移100个单位,也就是上面下方的图。

其他情况同理,这就是表面上scrollTogetScrollY的用法,其实记住这些也就够用了,但是为了更深入理解还是源码最有用。

这里有一步步带你深入源码解析scrollTo。

最重要的部分如下:

public void invalidate(Rect dirty) {
    final int scrollX = mScrollX;
    final int scrollY = mScrollY;
    invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, dirty.right - scrollX, dirty.bottom - scrollY, true, false);
}

这个invalidateInternal方法是被Viewinvalidate方法调用的,用来绘制新内容的位置,而这个dirty显然是旧的内容所表示的Rect,可以看出,在参数中设置的都是减去scrollX,scrollY,将上面的例子带入就能看出新内容是往反方向移动了。

你可能感兴趣的:(android)