[关闭]
@946898963 2019-12-31T08:46:33.000000Z 字数 2232 阅读 732

View的滑动

Android绘图


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

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

使用scrollTo/scrollBy

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

  1. public void scrollTo(int x, int y) {
  2. if (mScrollX != x || mScrollY != y) {
  3. int oldX = mScrollX;
  4. int oldY = mScrollY;
  5. mScrollX = x;
  6. mScrollY = y;
  7. invalidateParentCaches();
  8. onScrollChanged(mScrollX, mScrollY, oldX, oldY);
  9. if (!awakenScrollBars()) {
  10. postInvalidateOnAnimation();
  11. }
  12. }
  13. }
  1. public void scrollBy(int x, int y) {
  2. scrollTo(mScrollX + x, mScrollY + y);
  3. }

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中有两个重要的成员变量,mScrollX,mScrollY.它们分别代表视图内容(view content)水平方向和竖直方向的滚动距离。我们可以通过setScrollX和setScrollY来个函数来改变它们的值,从而来滚动视图的内容。在这里需要强调的是,mScrollX和mScrollY会导致视图内容(view content)变化,但是不会影响视图背景(background)。

Android Scroll 详解 (一):基础知识

使用动画

使用动画移动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. ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) tv_test.getLayoutParams();
  2. marginLayoutParams.leftMargin+=100;
  3. tv_test.setLayoutParams(marginLayoutParams);
  4. // 或者 tv_test.requestLayout();

三种方式对比

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

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

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注