在android中每一个view里都有这两个方法,所以理论上所有的view都是可以滑动的。
关于这两者,官网上是这样说的:这两者的介绍只有一字之差,一个是“move”,一个是“set”,因此,我的理解是scrollTo是相对于view的初始位置的,是不会变的。而scrollBy是相对于当前位置的,位置一直是移动的。
这里写一个demo如下:
public void btnClick(View view) {
switch (view.getId()) {
case R.id.scrollerToBtn:
//scrollTo相对于view的初始位置移动,所以这里view无论点击多少次,都只会相对于view的初始位置移动一定距离。
mLayout.scrollTo(getResources().getDimensionPixelSize(R.dimen.a), getResources().getDimensionPixelSize(R.dimen.b));
break;
case R.id.scrollerByBtn:
//scrollBy相对于view的当前位置移动,所以此处view是每点击一次就向右下角移动一次的。
mLayout.scrollBy(getResources().getDimensionPixelSize(R.dimen.a), getResources().getDimensionPixelSize(R.dimen.b));
break;
}
}
布局文件也就是两个按钮,这里需要注意下如果scrollTo()里直接写int型的像素值的话,编辑器可能会报错(运行正常)。建议写在dimen.xml文件里,也便于维护。
我们再来看看view里的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则是实现了“绝对滑动”。 需要注意的一点就是mScrollX/mScrollY这两个属性的规则,mScrollX表示的是view的左边缘到view的内容的左边缘的水平距离,类似的,mScrollY表示的是view的上边缘与view内容的上边缘的竖直方向的距离。
基于scrollTo/scrollBy的特性,我们可以很容易的利用它们来实现view的滑动,解决一些常见的问题,比如,登陆界面的键盘遮挡输入框的问题。但是需要注意的是,使用这两个方法进行view的滑动,只能对view的内容进行滑动,对于view本身并不能滑动。