Scoller 弹性滑动对象,用于实现View的弹性滑动。在说弹性滑动之前,我们先来看一下View常用的滑动方式。

  • 第一种:通过View本身提供的scrollTo / scrollBy 方法来实现滑动。
  • 第二种:通过动画给View 施加平移效果来实现滑动。
  • 第三种:通过改变View的LayoutParams 使得View 重新布局从而实现滑动

1.使用scrollTo /scrollBy

View提供了专门的方法来实现这个功能,那就是scrollerTo 和 scrollerBy,我们先来看一下这俩个方法的实现

   /**设置View的滚动位置,*这会调用 onScrollChanged(int,int,int,int)并且视图会失效** @param x 要滚动到的X位置* @param y 要滚动到的y位置*/public void scrollTo(int x,int y){if(mScrollX !=x || mScrollY !=y){int oldX= mScrollX; //当前控件x,y的位置,移动前int oldY= mScrollY;mScrollX=x;//x,y将要移动到的位置,传入值mScrollY=y;invalidateParentCaches();//进行滑动改变onScrollChanged(mScrollX,mScrollY,oldX,oldY);if(!awakenScrollBars()){postInvalidateOnAnimation();}}}/*** 移动视图的滚动位置。* 这将导致调用onScrollChanged(int,int,int,int)* 并且视图会失效* * @param x 水平滚动的像素数量* @param y 垂直滚动的像素数量*/public void scrollBy(int x, int y) {scrollTo(mScrollX + x, mScrollY + y);}

从源码可以看出:scrollBy 也调用了scrollTo方法,只不过

  • scrollTo实现了基于所传参数的滑动
  • scrollBy实现了基于当前位置的相对滑动

在滑动过程中

  • mScrollX:它的值总是等于View左边缘和View内容左边缘在水平方向上的距
  • mScrollY:它的值总是等于View上边缘和View内容上边缘在竖直方向上的距离

View边缘是指View的位置,由四个顶点组成
View内容边缘是指View中内容的边缘

即只能将View的内容进行移动,并不能将View本身进行移动

mScrollX,mScrollY 的单位是像素,可以通过getScrollX / getScrollY 获得。并且
当View左边缘在View内容左边缘的右边时,mScrollX 为正值,反之为负
当View上边缘在View内容上边缘的下边时,mScrollY为正值,反之为负

从传值角度来讲,如果你想让

  • View从左往右移动,那么mScrollX传负值,即scrollTo / scrollBy 第一个参数传负值

  • View从上往下移动,那么mScrollY传负值,即scrollTo / scrollBy 第而个参数传负值

反之,为正值。如下图

贴上代码

2.使用动画

通过动画我们能让一个View进行平移,而平移就是滑动,使用动画来移动View,主要是操作View的translationX和 translationY 属性,既可以采用传统的View动画,也可以采用属性动画,如果采用属性动画的话,为了兼容3.0一下版本,需要采用开源动画库nineoldandroids。动画相关可以看这里

compile'com.nineoldandroids:library:2.4.0'

采用View动画的代码,如下

<set xmlns:android="http://schemas.android.com/apk/res/android"android:fillAfter="true"><!--fillAfter 为true表示 保留动画后的状态--><!--interpolator 插值器--><translate
        android:duration="3000"android:toXDelta="200"android:toYDelta="0"android:fromXDelta="0"android:fromYDelta="0"android:interpolator="@android:anim/linear_interpolator"></translate>
</set>

使用View动画的缺点:

View 动画是对View 的影像做操作,它并不能正真改变View的位置参数,包括宽/高。假如我们通过View动画将一个Button向右移动100px,并且这个View设置的有单击事件,你会惊奇的发现,单击新位置无法触发onClick事件,而单击原始位置则可以触发onClick事件。因为不管Button怎么做变换,但是他的位置信息(四个顶点和宽 / 高)并不会随着动画而改变,因此在系统眼里,这个Button没有发生任何改变,它的真身仍然在原始位置

上述平移如果采用属性动画,就更简单了,

 ObjectAnimator.ofFloat(tv2,"translationX",0,100).setDuration(3000).start();

贴上完整代码

/**
* View 的滑动 2
* 动画
* 操作简单,主要用于没有否交互的View 和实现复杂的动画效果
*/
tv2=findViewById(R.id.tv2);
tv2.setOnClickListener(new View.OnClickListener() {@Override
public void onClick(View v) {tv2.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate_1));//或ObjectAnimator.ofFloat(tv2,"translationX",0,100).setDuration(3000).start();}
});

3.改变布局参数

改变布局参数,即改变LayouParams.比如我们想把一个Button向右平移100px,我们只需要将这个Button的LayoutParams 里的 marginLeft 参数的值增加100px 即可。我们还可以再Button左边放一个View 默认宽度为0,当需要Button右移时,给这个View设置宽度。

tv3.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) tv3.getLayoutParams();params.leftMargin += 100;tv3.setLayoutParams(params);}
});

各种滑动方式对比

  • scrollTo /scrollBy :操作简单,适合对View内容的滑动
  • 动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果
  • 改变布局参数:操作 稍微复杂,适用于有交互的View

Scroller

应用场景:当我们需要实现有过度效果的动画时就可以使用 Scroller。应为scrollTo /scrollBy 的滑动过程是瞬间完成的

先看一下Scroller的 典型代码它是固定的

 Scroller mScroller=new Scroller(mContent);//缓慢滚动到指定位置private void smoothScrollTo(int destX,int destY){int scrollX=getScrollX();int deltaX=destX-scrollX;//1000ms 内滑向destX,效果就是慢慢滑动mScroller.startScroll(scrollX,0,deltaX,0,1000);invalidate();}@Overridepublic void computeScroll() {if(mScroller.computeScrollOffset()){scrollTo(mScroller.getCurrX(),mScroller.getCurrY());postInvalidate();}}

接下来我们再看一下startScroll 方法。

/*** startX ,startY 表示的是滑动的起点** dx,dy 表示的是要滑动的距离** duration 表示的是整个滑动过程完成所需要的时间*/public void startScroll(int startX, int startY, int dx, int dy, int duration) {mMode = SCROLL_MODE;mFinished = false;mDuration = duration;mStartTime = AnimationUtils.currentAnimationTimeMillis();mStartX = startX;mStartY = startY;mFinalX = startX + dx;mFinalY = startY + dy;mDeltaX = dx;mDeltaY = dy;mDurationReciprocal = 1.0f / (float) mDuration;}

我们看到startScroll 方法内部只是保留了我们传递的几个参数而已,并没有做滑动操作,那么Scroller是如何实现弹性滑动的呢 ?

其答案就在 startScroll 下面的 invalidate 方法。invalidate 方法导致View重绘,在View的 draw 方法中又回去调用computeScroll 方法,(computeScroll需要我们自己去实现) 而computeScroll 方法又会去向Scroller 获取当前的scrollX 和scrollY ,然后通过scrollTo 方法实现滑动,接着有调用 postInvalidate 方法来进行第二次重绘,这一次重绘的过程和第一次重绘一样,还是会导致computeScroll 方法被调用;然后继续向Scroller 获取当前的scrollX 和 scrollY ,并通过scrollTo 方法滑动到新的位置。View每一次的重绘都会导致View进行小幅度的滑动,而多次的小幅度滑动就组成了弹性滑动,这就是Scroller 的工作机制。如此反复,直到整个滑动过程结束。

接下来我们看一下Scroller 的 computeScrollOffset 方法的实现,如下

public boolean computeScrollOffset() {if (mFinished) {return false;}int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);if (timePassed < mDuration) {switch (mMode) {case SCROLL_MODE:final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);mCurrX = mStartX + Math.round(x * mDeltaX);mCurrY = mStartY + Math.round(x * mDeltaY);break;......}}
}

可以看到,这个方法是根据时间流逝百分比来算出scrollX 和 scrollY 改变的百分比并计算出当前的值。这个过程类似动画中的插值器。 动画相关可以看这里

同样的,可以使用动画来实现View的弹性滑动,代码如下

private void performAnimation(final View target, final int start, final int end) {ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//整型估值器private IntEvaluator intEvaluator = new IntEvaluator();@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR1)@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Log.e(TAG, "onAnimationUpdate: 进度:" + animation.getAnimatedValue());//获取当前进度占整个动画的比例,浮点型 0-1之间float fraction = animation.getAnimatedFraction();target.getLayoutParams().width = intEvaluator.evaluate(fraction, start, end);target.requestLayout();}});valueAnimator.setDuration(5000).start();}

Android Scroller相关推荐

  1. 代码解说Android Scroller、VelocityTracker

    在编写自己定义滑动控件时经常会用到Android触摸机制和Scroller及VelocityTracker.Android Touch系统简单介绍(二):实例具体解释onInterceptTouchE ...

  2. Android Scroller与computeScroll方法的调用关系

    2019独角兽企业重金招聘Python工程师标准>>> Android ViewGroup中的Scroller与computeScroll的有什么关系? 答:没有直接的关系 知道了答 ...

  3. Android Scroller简单用法

    Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(conte ...

  4. Android Scroller 使用详解

    1.Scroller到底是什么? 答:Scroller只是个计算器,提供插值计算,让滚动过程具有动画属性,但它并不是View,只是单纯地为滑动提供计算. 2.Scroller只是提供计算,那谁来让Vi ...

  5. Android Scroller完全解析,关于Scroller你所需知道的一切

    2016大家新年好!这是今年的第一篇文章,那么应CSDN工作人员的建议,为了能给大家带来更好的阅读体验,我也是将博客换成了宽屏版.另外,作为一个对新鲜事物从来后知后觉的人,我终于也在新的一年里改用Ma ...

  6. Android Scroller用法

    为什么80%的码农都做不了架构师?>>>    概述 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义 ...

  7. Android Scroller的使用及自我理解

    2019独角兽企业重金招聘Python工程师标准>>> 以前做一个看书的项目时,有个翻书的功能,当手指滑动书页移动一段然后抬起后,需要页面view自动完成剩余的操作: 1.当滑动距离 ...

  8. [Android自定义控件] Android Scroller工具类和GestureDetector的简单用法

    转载:http://ipjmc.iteye.com/blog/1615828 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View ...

  9. Android Scroller类的详细分析

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...

  10. android scroller,深入理解Android中Scroller的滚动原理

    View的平滑滚动效果 什么是实现View的平滑滚动效果呢,举个简单的例子,一个View从在我们指定的时间内从一个位置滚动到另外一个位置,我们利用Scroller类可以实现匀速滚动,可以先加速后减速, ...

最新文章

  1. 马斯克“做空”特斯拉
  2. HTTP API 自动化测试从手工测试到平台的演变
  3. RESTLET开发实例(二)使用Component、Application的REST服务
  4. umask及文件默认和原始权限说明
  5. 连接到多台mysql_Oracle通过dblink连接到多台MySQL
  6. CodeForces - 1263A Sweet Problem(思维,水题)
  7. 从页面底部向上弹出dialog,消失时逐渐向下(转)
  8. Linux 后台开发运维人员常用的Linux命令汇总
  9. HTMLParser使用
  10. 拒绝:请求的对资源的访问被拒绝:泊坞窗
  11. matlab 相位谱_电气信息类专业课程之matlab系统仿真 第九章 提高仿真能力需要案例(1)...
  12. html站点的定义,HTML是什么?您构建网页的一站式解决方案
  13. 数据挖掘导论——Python练习
  14. 什么是单页面应用SPA?和多页面应用的区别?
  15. Groovy(六)groovy闭包
  16. 数据分析中的概率分析经验总结:正态分布随机数置信水平
  17. UIview 添加触摸.手势
  18. 带你走进缓存世界(1):漫谈缓存
  19. windows开源工具大全
  20. 试验设计与数据处理_【工作动态】规划院组织开展国内首次AisaIBIS超光谱仪机载系统挂飞综合试验...

热门文章

  1. Wayland (简体中文)
  2. python中怎么编写程序_python写完程序怎么运行
  3. 通过session实现用户的登录与登出功能
  4. 计算机信息安全四大要素,信息安全四大要素-信息安全包括四大要素
  5. Python安装.whl文件流程及问题解决
  6. 细讲如何判断文法是否是LL(1)文法
  7. sci影响因子小于1计算机,单位入编要求两篇SCI,影响因子大于1.0就可以,请问难吗?...
  8. 2021-04-23
  9. Elasticsearch通过_update_by_query和script批量修改文档
  10. 服务器安装嵌入式系统,嵌入式设备连接云服务器