Android Scroller
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相关推荐
- 代码解说Android Scroller、VelocityTracker
在编写自己定义滑动控件时经常会用到Android触摸机制和Scroller及VelocityTracker.Android Touch系统简单介绍(二):实例具体解释onInterceptTouchE ...
- Android Scroller与computeScroll方法的调用关系
2019独角兽企业重金招聘Python工程师标准>>> Android ViewGroup中的Scroller与computeScroll的有什么关系? 答:没有直接的关系 知道了答 ...
- Android Scroller简单用法
Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(conte ...
- Android Scroller 使用详解
1.Scroller到底是什么? 答:Scroller只是个计算器,提供插值计算,让滚动过程具有动画属性,但它并不是View,只是单纯地为滑动提供计算. 2.Scroller只是提供计算,那谁来让Vi ...
- Android Scroller完全解析,关于Scroller你所需知道的一切
2016大家新年好!这是今年的第一篇文章,那么应CSDN工作人员的建议,为了能给大家带来更好的阅读体验,我也是将博客换成了宽屏版.另外,作为一个对新鲜事物从来后知后觉的人,我终于也在新的一年里改用Ma ...
- Android Scroller用法
为什么80%的码农都做不了架构师?>>> 概述 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义 ...
- Android Scroller的使用及自我理解
2019独角兽企业重金招聘Python工程师标准>>> 以前做一个看书的项目时,有个翻书的功能,当手指滑动书页移动一段然后抬起后,需要页面view自动完成剩余的操作: 1.当滑动距离 ...
- [Android自定义控件] Android Scroller工具类和GestureDetector的简单用法
转载:http://ipjmc.iteye.com/blog/1615828 Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View ...
- Android Scroller类的详细分析
尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...
- android scroller,深入理解Android中Scroller的滚动原理
View的平滑滚动效果 什么是实现View的平滑滚动效果呢,举个简单的例子,一个View从在我们指定的时间内从一个位置滚动到另外一个位置,我们利用Scroller类可以实现匀速滚动,可以先加速后减速, ...
最新文章
- 马斯克“做空”特斯拉
- HTTP API 自动化测试从手工测试到平台的演变
- RESTLET开发实例(二)使用Component、Application的REST服务
- umask及文件默认和原始权限说明
- 连接到多台mysql_Oracle通过dblink连接到多台MySQL
- CodeForces - 1263A Sweet Problem(思维,水题)
- 从页面底部向上弹出dialog,消失时逐渐向下(转)
- Linux 后台开发运维人员常用的Linux命令汇总
- HTMLParser使用
- 拒绝:请求的对资源的访问被拒绝:泊坞窗
- matlab 相位谱_电气信息类专业课程之matlab系统仿真 第九章 提高仿真能力需要案例(1)...
- html站点的定义,HTML是什么?您构建网页的一站式解决方案
- 数据挖掘导论——Python练习
- 什么是单页面应用SPA?和多页面应用的区别?
- Groovy(六)groovy闭包
- 数据分析中的概率分析经验总结:正态分布随机数置信水平
- UIview 添加触摸.手势
- 带你走进缓存世界(1):漫谈缓存
- windows开源工具大全
- 试验设计与数据处理_【工作动态】规划院组织开展国内首次AisaIBIS超光谱仪机载系统挂飞综合试验...
热门文章
- Wayland (简体中文)
- python中怎么编写程序_python写完程序怎么运行
- 通过session实现用户的登录与登出功能
- 计算机信息安全四大要素,信息安全四大要素-信息安全包括四大要素
- Python安装.whl文件流程及问题解决
- 细讲如何判断文法是否是LL(1)文法
- sci影响因子小于1计算机,单位入编要求两篇SCI,影响因子大于1.0就可以,请问难吗?...
- 2021-04-23
- Elasticsearch通过_update_by_query和script批量修改文档
- 服务器安装嵌入式系统,嵌入式设备连接云服务器