View的滑动

实现View的滑动有三种方式:

  • 通过View本身提供的scrollTo/scrollBy方法实现滑动
  • 通过给View施加平移动画实现滑动
  • 通过改变View的LayoutParams使得View重新布局从而实现滑动

使用scrollTo/scrollBy

View 内部提供了scrollTo和scrollBy方法来实现滑动,scrollTo和scrollBy的实现源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
 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();
}
}
}
1
2
3
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}

scrollBy实际调用了scrollTo,它实现了基于当前位置的相对滑动,而scrollTo则实现了绝对滑动。

需要注意的是scrollTo和scrollBy只能改变View的内容位置而不能改变View在布局中的位置。

从源码可以看到两个值mScrollX和mScrollY,这两个值是滑动偏移量,其单位为像素,可以通过getScrollX和getScrollY方法获得。

滑动过程中,滑动偏移量mScrollX的值总是等于View的左边缘和View的内容的左边缘在水平方向的距离;滑动偏移量mScrollY的值总是等于View的上边缘和View的内容的上边缘在垂直方向的距离。也就是说当View的左边缘位于View的内容的左边缘的右边的时候,mScrollX为正值,反之为负值;当View的上边缘在View的内容的上边缘的下边的时候,mScrollY为正值,反之为负值。换句话说,如果从左向右滑动,则mScrollX为负值,反之为正值;如果从上向下滑动,则mScrollY为负值,反之为正值。

总结:滑动偏移量mScrollX和mScrollY的正负与实际滑动方向相反,即从左向右滑动,mScrollX为负值,从上往下滑动mScrollY为负值。

使用动画

使用动画移动View,主要是操作View的translationX和translationY属性,既可以采用传统的View动画,也可以采用属性动画,如果使用属性动画,为了能够兼容3.0以下的版本,需要采用开源动画库nineolddandroids。 需要注意的是,在3.0以下的手机上采用nineolddandroids库实现的属性动画,本质上仍然是View动画,并不会真正改变属性。如使用属性动画:(View在100ms内向右移动100像素)

1
“ObjectAnimator.ofFloat(targetView,"translationX",0,100).setDuration(100).start();”

View动画是对View的影像做操作,并不能真正的改变View的位置,这就导致了一个问题,那就是View移动后,点击事件仍然还是停留在原来的位置。这是因为View移动后View的位置信息(四个定点和宽高)并不会随着移动而改变,见View的基础知识
解决方案:

  • 采用属性动画。
  • 采用双View,在原位置和移动后的位置分别设置一个View,移动后隐藏原来的View。

改变布局属性

通过改变布局属性来移动View,即改变LayoutParams。

1
2
3
4
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) tv_test.getLayoutParams();
marginLayoutParams.leftMargin+=100;
tv_test.setLayoutParams(marginLayoutParams);
// 或者 tv_test.requestLayout();

三种方式对比

scrollTo和scrollBy方式:
操作简单,并没有改变View的位置,改变的是View的内容的位置,适合对View的内容进行移动。
动画方式:
操作简单,采用View动画,并没有改变View的位置,改变的只是View的影像,而且点击事件不会移动;采用属性动画,真正改变了View的位置,而且点击事件会移动。实现比较复杂的效果的时候,建议选择属性动画的方式。
改变位置参数方式:
操作复杂,真正改变了View的位置,而且点击事件也会随着View移动,适合有交互的View。

参考资料:
《Android开发艺术探索》

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器