[学习总结]3、Android---Scroller类(左右滑动效果常用的类)
参考资料:http://blog.csdn.net/vipzjyno1/article/details/24592591 非常感谢这个兄弟!
在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现。。
先来看一下demo的效果: 下载地址

学习Scroller这个类之前你需要学习一下下面的知识:
1、Scroller的2个方法scrollTo()和scrollBy()不了解的点这里 scrollTo()和scrollBy()的区别 知道的跳过这一步
2、屏幕中的触摸事件分发机制(这一块在涉及到触摸的任何情况下都十分重要)现在自行百度吧,我还没有整理好关于事件分发的资料,后续我会整理一篇。
[学习总结]4、Android的ViewGroup中事件的传递机制(一)
下面看一下这个类的概述:
This class encapsulates scrolling. You can use scrollers (Scroller or OverScroller) to collect the data you need to produce a scrolling animation—for example, in response to a fling gesture. Scrollers track scroll offsets for you over time, but they don't automatically apply those positions to your view. It's your responsibility to get and apply new coordinates at a rate that will make the scrolling animation look smooth.
To track the changing positions of the x/y coordinates, use computeScrollOffset(). The method returns a boolean to indicate whether the scroller is finished. If it isn't, it means that a fling or programmatic pan operation is still in progress. You can use this method to find the current offsets of the x and y coordinates, for example:
跟踪变化的x / y坐标的位置,通过computeScrollOffset()方法监听返回的布尔值来指示滚动动作是否完成。如果返回为false,说明滚动已经结束。返回true,它意味着操作仍在进行中。您可以使用
int currX = mScroller.getCurrX(); //滚动的X滚动距离
int currY = mScroller.getCurrY(); //滚动的y滚动距离
这个方法来找到当前的x和y坐标的偏移量。
在看一下构造函数
| Public Constructors | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
Create a Scroller with the default duration and interpolator.
|
|||||||||||
|
Create a Scroller with the specified interpolator.
|
|||||||||||
|
Create a Scroller with the specified interpolator.
|
|||||||||||
Interpolator interpolator 表示的是动画插入器,你可以设定相应的效果给它。
下面是所有的插入器
AccelerateDecelerateInterpolator 动画效果:开始和结束都是缓慢的,通过中间时候加速
AccelerateInterpolator, 动画效果:开始缓慢,之后加速
AnticipateInterpolator, 动画效果:开始后退,然后前进
AnticipateOvershootInterpolator, 动画效果:开始后退,之后前进并超过终点位置,最终退回到终点
BounceInterpolator, 动画效果:慢慢反弹到,弹性衰减到结束
CycleInterpolator, 动画效果:重复循环动画,速度变化遵循正弦定律
DecelerateInterpolator, 动画效果:刚开始快速,之后减速
LinearInterpolator, 动画效果:不断的变化
OvershootInterpolator 动画效果:像前超越最终点然后回来
可以通过初始化构造方法Scroller(Context context, Interpolator interpolator)给它相应的动画效果。
Interpolator interpolator = new BounceInterpolator();
在看一下他的公用方法:
| blic Methods | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
void
|
abortAnimation() 停止动画,滚到最终的x,y位置中止动画
|
||||||||||
|
boolean
|
computeScrollOffset() 当你想要知道新的位置时候,调用该方法。返回true:动画没结束
|
||||||||||
|
void
|
extendDuration(int extend) 延长滚动动画的时间。extend表示延迟时间(单位为毫秒)
|
||||||||||
|
void
|
fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY)
在fling(快速滑动,触摸屏幕后快意移动松开)的手势基础上开始滚动,滚动距离取决于fling的初速度。
|
||||||||||
|
final void
|
forceFinished(boolean finished) 强制终止滚动。
|
||||||||||
|
float
|
getCurrVelocity() 返回当前的速度
|
||||||||||
|
final int
|
getCurrX() 返回当前滚动的X方向的偏移量(距离原点X轴方向)
|
||||||||||
|
final int
|
getCurrY() 返回当前滚动的Y方向的偏移量(距离原点Y轴方向)
|
||||||||||
|
final int
|
getDuration() 返回滚动事件的持续时间(毫秒)
|
||||||||||
|
final int
|
getFinalX() 返回滚动结束的X方向的偏移量(注:只针对fling 手势有效)(距离原点X轴方向)
|
||||||||||
|
final int
|
getFinalY() 返回滚动结束的Y方向的偏移量(注:只针对fling 手势有效)(距离原点Y轴方向)
|
||||||||||
|
final int
|
getStartX() 返回滚动起始点的X方向偏移量(距离原点X轴方向)
|
||||||||||
|
final int
|
getStartY() 返回滚动起始点的Y方向偏移量.(距离原点Y轴方向)
|
||||||||||
|
final boolean
|
isFinished() 返回scroller滚动是否结束,true:滚动结束 false:还在滚动
|
||||||||||
|
void
|
setFinalX(int newX) 设置scroller的终止时X方向偏移量
|
||||||||||
|
void
|
setFinalY(int newY) 设置scroller的终止时Y方向偏移量
|
||||||||||
|
final void
|
setFriction(float friction)
The amount of friction applied to flings.
|
||||||||||
|
void
|
startScroll(int startX, int startY, int dx, int dy)
提供起始点和滚动距离,调用该方法进行滚动。(此处默认时间为250ms)
|
||||||||||
|
void
|
startScroll(int startX, int startY, int dx, int dy, int duration)
提供起始点和滚动距离以及滚动时间,调用该方法进行滚动。
|
||||||||||
|
int
|
timePassed() 返回自滚动开始经过的时间(毫秒)
|
||||||||||
源码
下面看看以上方法的源码实现:
知识点1:computeScrollOffset()方法
1 /**
2 * Call this when you want to know the new location. If it returns true,
3 * the animation is not yet finished. loc will be altered to provide the
4 * new location.
5 */
6 public boolean computeScrollOffset() {
7 if (mFinished) {
8 return false; //已经完成了本次动画,直接返回为false
9 }
10 int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
11
12 if (timePassed < mDuration) {
13 switch (mMode) {
14 case SCROLL_MODE:
15 float x = timePassed * mDurationReciprocal;
16
17 if (mInterpolator == null)
18 x = viscousFluid(x);
19 else
20 x = mInterpolator.getInterpolation(x);
21
22 mCurrX = mStartX + Math.round(x * mDeltaX);
23 mCurrY = mStartY + Math.round(x * mDeltaY);
24 break;
25 case FLING_MODE:
26 final float t = (float) timePassed / mDuration;
27 final int index = (int) (NB_SAMPLES * t);
28 float distanceCoef = 1.f;
29 float velocityCoef = 0.f;
30 if (index < NB_SAMPLES) {
31 final float t_inf = (float) index / NB_SAMPLES;
32 final float t_sup = (float) (index + 1) / NB_SAMPLES;
33 final float d_inf = SPLINE_POSITION[index];
34 final float d_sup = SPLINE_POSITION[index + 1];
35 velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
36 distanceCoef = d_inf + (t - t_inf) * velocityCoef;
37 }
38 mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
39
40 mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
41 // Pin to mMinX <= mCurrX <= mMaxX
42 mCurrX = Math.min(mCurrX, mMaxX);
43 mCurrX = Math.max(mCurrX, mMinX);
44
45 mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
46 // Pin to mMinY <= mCurrY <= mMaxY
47 mCurrY = Math.min(mCurrY, mMaxY);
48 mCurrY = Math.max(mCurrY, mMinY);
49 if (mCurrX == mFinalX && mCurrY == mFinalY) {
50 mFinished = true;
51 }
52 break;
53 }
54 }
55 else {
56 mCurrX = mFinalX;
57 mCurrY = mFinalY;
58 mFinished = true;
59 }
60 return true;
61 }
调用该方法判断滚动是否还在继续,mFinished属性判断是否滚动完成,如果滚动完成了,mFinished = true,computeScrollOffset() 返回false。
知识点2:computeScroll()方法
1 /**
2 * Called by a parent to request that a child update its values for mScrollX
3 * and mScrollY if necessary. This will typically be done if the child is
4 * animating a scroll using a {@link android.widget.Scroller Scroller}
5 * object.
6 */由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制
7 public void computeScroll() {
8 }
知道了computeScrollOffset()这个判断是否滚动的方法,那我们必须要有监听滑屏控制,并且重绘,在Android框架中的VIEW类中就提供了computeScroll()这个方法去控制该流程。在绘制View时,会在draw()过程调用该方法。因此, 再配合使用Scroller实例,我们就可以获得当前应该的偏移坐标,手动使View/ViewGroup偏移至该处。
注:在使用Scroller这个类实现偏移控制,一般自定义View/ViewGroup都需要重载该方法 。
具体实现:
1 @Override
2 public void computeScroll() {
3 if (mScroller.computeScrollOffset()) {
4 scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
5 // 更新界面
6 postInvalidate();
7 isMoving = true;
8 } else {
9 isMoving = false;
10 }
11 super.computeScroll();
12 }
知识点3:startScroll()方法
1 /**
2 * Start scrolling by providing a starting point and the distance to travel.
3 *
4 * @param startX //水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
5 * @param startY //垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
6 * @param dx //水平方向滑动的距离,正值会使滚动向左滚动
7 * @param dy //垂直方向滑动的距离,正值会使滚动向上滚动
8 * @param duration //滚动持续时间
9 */
10 public void startScroll(int startX, int startY, int dx, int dy, int duration) {
11 mMode = SCROLL_MODE;
12 mFinished = false;
13 mDuration = duration;
14 mStartTime = AnimationUtils.currentAnimationTimeMillis();
15 mStartX = startX;
16 mStartY = startY;
17 mFinalX = startX + dx;
18 mFinalY = startY + dy;
19 mDeltaX = dx;
20 mDeltaY = dy;
21 mDurationReciprocal = 1.0f / (float) mDuration;
22 }
该方法以提供的起始点和将要滑动的距离开始滚动,我们可以使用该方法达到自动滚动的效果。在滚动中,如果符合什么条件,可以调用该方法让它滚动到相对应的地方。
着重点:
在界面滚动中,你必须搞清楚和scrollTo和scrollBy之间的区别所在:android 布局之滑动探究 scrollTo 和 scrollBy 方法使用说明

使用思路流程:
如果你使用Scroller,流程如下:
1.可以在自定义的布局中,按照需求初始化Scroller构造函数。
2.重写onInterceptTouchEvent(MotionEvent ev)方法,看看是否要拦截相关的点击时间。
3.重写onTouchEvent(MotionEvent event)方法,根据触摸屏上的动作使用computeScroll()以及scrollTo 和 scrollBy方法进行根据手指对布局进行滑动效果。
4.在触摸操作结束(MotionEvent.ACTION_UP)的时候,调用startScroll(int startX, int startY, int dx, int dy, int duration)方法,进行动画自动操作,来完成整个滚动流程。
对于Scroller类大体的使用和介绍已经完毕,结合上面介绍的这些看一下上面的demo我相信你的收获一定很大的。这东西虽然都不是我写的,但是都是我读懂之后才放上来的,1是为了给大家分享一下,2就是我自己的笔记。
[学习总结]3、Android---Scroller类(左右滑动效果常用的类)的更多相关文章
- Android三种左右滑动效果 手势识别
Android三种左右滑动效果 手势识别(转) 手势识别 1.onCreate中添加GestureDetector mGestureDetector; //监听手势事件 mGestureDetec ...
- Android快速开发系列 10个常用工具类
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38965311,本文出自[张鸿洋的博客] 打开大家手上的项目,基本都会有一大批的辅 ...
- 【转】 Android快速开发系列 10个常用工具类 -- 不错
原文网址:http://blog.csdn.net/lmj623565791/article/details/38965311 转载请标明出处:http://blog.csdn.net/lmj6235 ...
- Android三种左右滑动效果 手势识别(转)
本示例演示在Android中实现带渐显按钮的左右滑动效果. 关于滑动效果,在我的上一篇博文中提到过,有兴趣的朋友可以访问: http://www.cnblogs.com/hanyonglu/archi ...
- Android 常用工具类之SPUtil,可以修改默认sp文件的路径
参考: 1. 利用Java反射机制改变SharedPreferences存储路径 Singleton1900 2. Android快速开发系列 10个常用工具类 Hongyang import ...
- java面试复习重点:类的管理及常用工具,教你抓住面试的重点!
java复习: 类的管理及常用工具类 包 写在程序文件的第一行 一个Java 源文件中只能声明一个包, 且声明语句只能作为源文件的第一条指令 导入类能导入非public类,但是不能用因为在其他包缺省的 ...
- android Scroller类的理解
Scroller 一个特例: **点击Button后可能View没有移动,要关闭硬件加速,这段代码中int detalX = (int) (event.getX() - downX)要更正. demo ...
- Android中ViewPager实现滑动条及与Fragment结合的实例教程
ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习Android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下 自主实现滑动指示条先上一个 ...
- 详解实现Android中实现View滑动的几种方式
注: 本文提到的所有三种滑动方式的完整demo:ScrollDemo 1. 关于View我们需要知道的 (1)什么是View? Android中的View类是所有UI控件的基类(Base class) ...
随机推荐
- Webshell 一句话木马
Webshell介绍 什么是 WebShell webshell就是以asp.php.jsp或者cgj等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门 由于 webshell其大多是 ...
- LeetCode 重排链表 OPPO笔试
重排链表 几个关键点: 1. 双指针(快慢指针找中点)(用于反转后一部分) 2. 反转后一部分 (reverse函数) 3. 合并链表 合并的时候在笔试的时候想了一种比我之前想的简单的方法 从slow ...
- Java oop三大特性(封装,继承,多态)
封装 顾名思义,就是将数据封装起来,提高数据的安全性.我们程序都是要追求"高内聚,低耦合".高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合:仅暴露少量的方法给外部使 ...
- Linux ns 6. Network Namespace 详解
文章目录 1. 简介 1.1 Docker Network 桥接模式配置 2. 代码解析 2.1 copy_net_ns() 2.2 pernet_list 2.2.1 loopback_net_op ...
- SpringCloud升级之路2020.0.x版-33. 实现重试、断路器以及线程隔离源码
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面两节,我们梳理了实现 Feign 断路器以及线程隔离的思路,并说明了如何优化目前的负 ...
- 第三课 Dubbo设计中的设计模式
责任链模式 责任链模式在Dubbo中发挥的作用举足轻重,就像是Dubbo框架的骨架.Dubbo的调用链组织是用责任链模式串连起来的. 责任链中的每个节点实现Filter接口,然后由ProtocolF ...
- 程序员PS技能(四):程序员创建PSD文件、展示简单PSD设计流程,上传PSD至蓝湖,并下载Demo切图
前言 本篇是程序员仿照ui设计创建psd且切图五个按钮效果上传至蓝湖,本篇篇幅较长,整体完成一个目标,没有分篇幅了. 前提条件 已经安装了PS,已经在PS上安装了蓝湖插件,并且曾经已经上传 ...
- Ubuntu軟件商店加載失敗的解決方法
Ubuntu軟件商店有的时候加载不出来,先用下面的试试 sudo apt install python-apt 如果不行,继续下面的方法 打开终端,运行下面的命令: sudo apt-get upda ...
- inux 下配置网卡的别名即网卡子IP的配置 转
what 什么是ip别名?用windows的话说,就是为一个网卡配置多个ip.when 什么场合增加ip别名能派上用场?布网需要.多ip访问测试.特定软件对多ip的需要...and so on. ho ...
- 关于JAVA中顺序IO的基本操作
关于JAVA中顺序IO的基本操作 写在前面 最近研究一下JAVA中的顺序IO,在网络上找了一会儿,发现少有详细的介绍,顾此在此处说说顺序IO,才学疏浅,如有不对,望赐教. 什么是顺序IO 事实上JAV ...