在实际开发中,我们总是会遇到View滑动的功能,那么可能就会用View的scrollTo(int x, int y)或者scrollBy(int x, int y)方法,但是当你使用这个方法之后,你会发现完全和你想的不是一回事!那么今天,我们就来了解一下,传说中的View的scrollTo(int x, int y)或者scrollBy(int x, int y)方法。如果你对Android 坐标系还不了解,那么请看这篇文章,Android View(一)-View坐标以及方法说明。
一.认识mScrollX和mScrollY。
我们需要认识View里面的两个变量,mScrollX和mScrollY,看看View是怎么定义的,
/**
* The offset, in pixels, by which the content of this view is scrolled
* horizontally.
* {@hide}
*/
@ViewDebug.ExportedProperty(category = "scrolling")
protected int mScrollX;
/**
* The offset, in pixels, by which the content of this view is scrolled
* vertically.
* {@hide}
*/
@ViewDebug.ExportedProperty(category = "scrolling")
protected int mScrollY;
获取mScrollX的值,View提供的方法,
/**
* 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;
}
获取mScrollY的值,View提供的方法,
/**
* 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;
}
那么我们需要知道mScrollX和mScrollY的变化规律:
(1).mScrollX的值总是等于View左边缘和View内容左边缘在水平方向的距离(mScrollX=X1-X2,,其中X1,表示View的左边缘,其中X2,表示View内容的左边缘),当View内容的左边缘位于View的左边缘的左边时,mScrollX大于零,即mScrollX为正值,反之为负值;
(2).mScrollY的值总是等于View上边缘和View内容上边缘在竖直方向的距离(mScrollY=Y1-Y2,,其中Y1,表示View的上边缘,其中Y2,表示View内容的上边缘),当View内容的上边缘位于View的上边缘的上边时,mScrollY大于零,即mScrollY为正值,反之为负值;
View边缘是指View的位置,由4个顶点组成,View内容的边缘是指View中的内容的边缘,mScrollX和mScrollY的单位为像素,默认情况,mScrollX和mScrollY都为零。我们简单理解就是,如果从右向左滑动时,mScyuollX大于零,反之小于零;如果从下往上滑动时,mScrollY大于零,反之小于零;
二.scrollTo(int x, int y) ,scrollBy(int x, int y)方法。PS: 我们需要先了解的是,这两个方法实际改变的是View里面的内容位置,或者说View里面的内容的在移动(滚动),不是View的位置发生变化。你可以写个Demo测试一下,看看具体是什么样!
1. scrollBy(int x, int y)方法,先看看View源码中这个方法的具体实现,如下,
/**
* 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(int x, int y)方法其实也是调用了scrollTo(int x, int y)方法,它是基于当前位置的相对滑动,接着我们就看看scrollTo(int x, int y) 方法。
/**
* 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();
}
}
}
scrollTo(int x, int y) ,则实现了基于参数的绝对滑动。if (mScrollX!= x || mScrollY!= y),x便赋值给mScrollX,y便赋值给mScrollY,所以,x和y不是坐标点,是偏移量。先来一张图,
这张图中,绿色的线框是LinearLayout,它里面的内容有TextView(也就是蓝色线框标识的区域),TextView里面红色的线框标识它里面内容区域。
通过上面的描述,我们可以了解到,当调用view.scrollTo(100, 0) 的时候,View里面的内容是向左移动的;当调用view.scrollTo(-100, 0) 的时候,View里面的内容是向右移动的;我们还是看几张图,可能会更明显一点,
这几张图,显示了当调用view.scrollTo()方法后的效果,同理view.scrollBy()方法的效果也类似,只是,当你调用view.scrollTo()方法后,View的内容是一步移动到指定的位置,而调用view.scrollBy()方法,每次都在现有的基础上移动一定的偏移量!
通过以上描述,我们可以知道,使用scrollTo(int x, int y) 和scrollBy(int x, int y),只能将View的内容进行移动,并不能将View的位置进行移动,也就是说,不管怎么滑动,View的位置一直都不会发生变化,一直都是初始位置。
也许有朋友要问,为何当调用view.scrollTo(100, 0) 时,内容反而是向左边移动呢?在此,就给大家介绍几篇文章来看一下!希望对大家有所帮助!(本人水平有限,有错误的地方,欢迎大家指出)
有关文章:Android学习Scroller(一)——View调用scrollTo()的理解及使用
Android scrollTo() scrollBy() Scroller讲解及应用
Android View中滚动 scrollTo scrollBy mScrollX mScrollY