Android View的scroll方法及属性

Android开发中,在自定义控件的时候,如果涉及到滑动事件,经常需要使用View提供的诸如scrollTo()、scrollBy()、getScrollX()、getScrollY()等方法。但在这些api的实际使用过程中,开发人员很容易在移动方向、移动距离上产生迷惑,本文通过图例总结了这四种方法的区别和联系。

在讲解之前,首先需要明白的一点时,在Android手机屏幕坐标系中,坐标原点(0, 0)位于左上角,X轴方向向右为正方向,但Y轴方向与“笛卡尔”坐标系中的Y轴方向相反,即向下为Y轴正方向。

Android View的scroll方法及属性_第1张图片
Android坐标系.png

同理,View相对于它的父容器ParentView的相对位置的坐标变化方向也是与上图坐标系方向一致的。下面是亦枫列举的关于scrollTo()、scrollBy()、getScrollX()和getScrollY()的一些知识点和容易混淆的地方。为了更好地讲述,先贴上源码:

    /**
     * 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()) {
                invalidate(true);
            }
        }
    }

    /**
     * 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);
    }
    /**
     * Return the scrolled left position of this view. This is the left edge of
     * the displayed part of your view. You do not need to draw any pixels
     * farther left, since those are outside of the frame of your view on
     * screen.
     *
     * @return The left edge of the displayed part of your view, in pixels.
     */
    public final int getScrollX() {
        return mScrollX;
    }

    /**
     * Return the scrolled top position of this view. This is the top edge of
     * the displayed part of your view. You do not need to draw any pixels above
     * it, since those are outside of the frame of your view on screen.
     *
     * @return The top edge of the displayed part of your view, in pixels.
     */
    public final int getScrollY() {
        return mScrollY;
    }
  • 滑动对象
    scrollTo和scrollBy用于滑动View的内容,而不是改变View本身所处的位置。所以,单独的View滑动很少见,更多的是ViewGroup调用scroll方法滑动子控件的位置。比如,使用TextView对象调用scrollTo或者ScrollBy方法,会发现TextView里面的文本内容的位置发生改变,而TextView本身所处的位置没有变化。

  • getScrollX()和getScrollY()
    返回值mScrollX和mScrollY分别表示距离起始位置的X轴或Y轴方向上的偏移量,而不是View在X轴或Y轴方向上的坐标值,用于记录偏移增量的两个变量。所以,mScrollX和mScrollY的初始值为0和0。

  • scrollTo(int x, int y)
    从源码中可以看出,scrollTo移动的目标位置x和y值是以初始化的mScrollX和mScrollY为参考点的,只要位置发生偏移,就对mScrollX和mScrollY赋新值。注意,这里的(x,y)理解为针对初始化值的偏移量,比如,我想移动到(100,100)这个位置,那么偏移量就是(0,0)-(100,100)=(-100,100),所以调用的时候就是view.scrollTo(-100, -100),这样才能达到我们想要的偏移效果。

  • scrollBy(int x, int y)
    从源码中可以看到,scrollBy依旧调用了scrollTo方法:scrollTo(mScrollX + x, mScrollY + y),只是参考点不再是初始化时的(0,0),相对于当前位置的偏移量。

最后,通过图例来说明上述所讲的内容。

初始化视图(为了展示效果,此处故意将子View和父View大小岔开):

Android View的scroll方法及属性_第2张图片
初始化视图.png

以scrollTo的正负值移动为例来说明移动方向:

Android View的scroll方法及属性_第3张图片
scrollTo(100,0).png
Android View的scroll方法及属性_第4张图片
scrollTo(-100,0).png

scrollBy(int x,int y)在正负值的移动方向和scrollBy一致,这里就不重复列举了。

欢迎欢迎关注作者微信公众号:技术鸟,一起学习,共同进步。

Android View的scroll方法及属性_第5张图片
技术鸟_微信二维码.gif

你可能感兴趣的:(Android View的scroll方法及属性)