Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)

在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现。。

例子相关博文:Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码

在广泛使用的侧边滑动导航开源库 --SlidingLayer其实就是使用到了Scroller类进行的实现,下载地址:GITHUB  ,下面要讲的不是这个库,而是这个库的实现过程中使用到的---Scroller类,懂了之后你看库的源码就知道,原来它是这样实现的。

Scroller类使用过程中,懂得以下机制可能会对开发更有帮助:

1.视图的VIEW的自定义以及其在屏幕中布局。

2.scrollTo()和scrollBy()方法的作用区别

可以点击此处了解:android 布局之滑动探究 scrollTo 和 scrollBy 方法使用说明

3.屏幕中的触摸事件分发机制(这一块在涉及到触摸的任何情况下都十分重要)

首先看看发开文档里面说了些什么:

android发开文档

开发文档参考链接:http://developer.android.com/reference/android/widget/Scroller.html

Scroller

一.结构关系

extends Object

二.概述

Class Overview



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
 
Scroller(Context context)

Create a Scroller with the default duration and interpolator.

 
Scroller(Context context, Interpolator interpolator)

Create a Scroller with the specified interpolator.

 
Scroller(Context context, Interpolator interpolator, boolean flywheel)

Create a Scroller with the specified interpolator.

Interpolator interpolator 表示的是动画插入器,你可以设定相应的效果给它。

Interpolator

implements TimeInterpolator


android.view.animation.Interpolator


Known Indirect Subclasses

AccelerateDecelerateInterpolatorAccelerateInterpolatorAnticipateInterpolatorAnticipateOvershootInterpolatorBounceInterpolatorCycleInterpolator,DecelerateInterpolatorLinearInterpolatorOvershootInterpolator

AccelerateDecelerateInterpolator     动画效果:开始和结束都是缓慢的,通过中间时候加速

AccelerateInterpolator,      动画效果:开始缓慢,之后加速

AnticipateInterpolator,       动画效果:开始后退,然后前进

AnticipateOvershootInterpolator,   动画效果:开始后退,之后前进并超过终点位置,最终退回到终点

BounceInterpolator,        动画效果:慢慢反弹到,弹性衰减到结束

CycleInterpolator,          动画效果:重复循环动画,速度变化遵循正弦定律

DecelerateInterpolator,        动画效果:刚开始快速,之后减速

LinearInterpolator,         动画效果:不断的变化

OvershootInterpolator         动画效果:像前超越最终点然后回来

可以通过初始化构造方法Scroller(Context context, Interpolator interpolator)给它相应的动画效果。

Interpolator interpolator = new BounceInterpolator();

四.公共方法

Public 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()方法

[java] view plaincopy

  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. if (timePassed < mDuration) {
  12. switch (mMode) {
  13. case SCROLL_MODE:
  14. float x = timePassed * mDurationReciprocal;
  15. if (mInterpolator == null)
  16. x = viscousFluid(x);
  17. else
  18. x = mInterpolator.getInterpolation(x);
  19. mCurrX = mStartX + Math.round(x * mDeltaX);
  20. mCurrY = mStartY + Math.round(x * mDeltaY);
  21. break;
  22. case FLING_MODE:
  23. final float t = (float) timePassed / mDuration;
  24. final int index = (int) (NB_SAMPLES * t);
  25. float distanceCoef = 1.f;
  26. float velocityCoef = 0.f;
  27. if (index < NB_SAMPLES) {
  28. final float t_inf = (float) index / NB_SAMPLES;
  29. final float t_sup = (float) (index + 1) / NB_SAMPLES;
  30. final float d_inf = SPLINE_POSITION[index];
  31. final float d_sup = SPLINE_POSITION[index + 1];
  32. velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
  33. distanceCoef = d_inf + (t - t_inf) * velocityCoef;
  34. }
  35. mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
  36. mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
  37. // Pin to mMinX <= mCurrX <= mMaxX
  38. mCurrX = Math.min(mCurrX, mMaxX);
  39. mCurrX = Math.max(mCurrX, mMinX);
  40. mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
  41. // Pin to mMinY <= mCurrY <= mMaxY
  42. mCurrY = Math.min(mCurrY, mMaxY);
  43. mCurrY = Math.max(mCurrY, mMinY);
  44. if (mCurrX == mFinalX && mCurrY == mFinalY) {
  45. mFinished = true;
  46. }
  47. break;
  48. }
  49. }
  50. else {
  51. mCurrX = mFinalX;
  52. mCurrY = mFinalY;
  53. mFinished = true;
  54. }
  55. return true;
  56. }

调用该方法判断滚动是否还在继续,mFinished属性判断是否滚动完成,如果滚动完成了,mFinished = true,computeScrollOffset() 返回false。

知识点2:computeScroll()方法

[java] view plaincopy

  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都需要重载该方法 。

具体实现:

[java] view plaincopy

  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()方法

[java] view plaincopy

  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类大体的使用和介绍已经完毕,之后会放上自己调用类实现的几个漂亮的效果。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-20 00:45:05

Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)的相关文章

Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)

在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.. 在广泛使用的侧边滑动导航开源库 --SlidingLayer其实就是使用到了Scroller类进行的实现,下载地址:GITHUB  ,下面要讲的不是这个库,而是这个库的实现过程中使用到的---Scroller类,懂了之后你看库的源码就知道,原来它是这样实现的. Scroller类使用过程中,懂得以下机制可能会对开发更有帮助: 1

ASP.NET综合管理ERP系统100%源码+全部开发文档

该系统开发环境为:VS2010,数据库采用SQL Server,框架为ASP.NET.源码包括全部文档说明,代码简单易懂,注释完整. 提示:如果没有安装水晶报表系统运行会报错,报表安装程序已经打包在源码中. 系统主要功能: 1. 执行模式 通过动态的管理个人及部门的目标任务和绩效,提高全员工能动性:日程安排只能提醒.建立畅通公共交流渠道.实现及时.准确.快速.高效的信息沟通和企业文化共享平台. 2.  办公模式 办公模式是将现代化管理理念导入动态工作流,通过无纸化协同办公,达到工作精细化.流程化

Android应用ViewDragHelper详解及部分源码浅析

[工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 很久没有更新博客了,忙里偷闲产出一篇.写这片文章主要是去年项目中的一个需求,当时三下五除二的将其实现了,但是源码的阅读却一直扔在那迟迟没有时间理会,现在拣起来看看吧,否则心里一直不踏实. 关于啥是ViewDragHelper,这里不再解释,官方下面这个解释已经很牛逼了,如下: /** * ViewDragHelper is a utility class for

Android View体系(七)从源码解析View的measure流程

相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源码解析Scroller Android View体系(五)从源码解析View的事件分发机制 Android View体系(六)从源码解析Activity的构成 前言 在上一篇我们了解了Activity的构成后,开始了解一下View的工作流程,就是measure.layout和draw.measure

Android View体系(五)从源码解析View的事件分发机制

相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源码解析Scroller 前言 三年前写过事件分发机制的文章但是写的不是很好,所以重新再写一篇,关于事件分发机制的文章已经有很多,但是希望我这篇是最简洁.最易懂的一篇. 1.处理点击事件的方法 View的层级 我们知道View的结构是树形的结构,View可以放在ViewGroup中,这个ViewGro

Android View体系(八)从源码解析View的layout和draw流程

相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源码解析Scroller Android View体系(五)从源码解析View的事件分发机制 Android View体系(六)从源码解析Activity的构成 Android View体系(七)从源码解析View的measure流程 前言 上一篇文章我们讲了View的measure的流程,接下来我们

ym——Android仿网易新闻导航栏PagerSlidingTabStrip源码分析

转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 前言 最近工作比较忙,所以现在才更新博文,对不住大家了~!言归正传,我们来说说这个PagerSlidingTabStrip,它是配合ViewPager使用的导航栏,网易新闻就是用的这个导航,我们仔细观察这个导航栏不仅他是跟着ViewPager滑动而滑动,而且指示器还会随着标题的长度而动态的变化长度,还可以改变多种样式哦~! · 下载地址: Github:https://github.

Android精品资源汇总,10个源码(持续更新)

最近一直在学习Android,在各大社区逛,总结下自己看到的一些不错的源码.希望可以给大家带来帮助. 1.Android精品源码:带动态效果的Button(按钮) 最喜欢各种效果的按钮了,没办法就是这么的呆萌是不是?带动态效果的Button(按钮)可要比静态的按钮炫酷的多了,大家看到效果图就知道了,那么Android开发者们快动手做一个自己喜欢的动态按钮吧! 很炫的效果图,源码下载点击:Android精品源码:带动态效果的Button(按钮) 2.一个漂亮的按钮库[Android精品] 一个不要

Android斗地主棋牌游戏牌桌实现源码下载

本次给大家分享下Android斗地主棋牌游戏牌桌实现源码下载如下:为了节约内存资源,每张扑克牌都是剪切形成的,当然这也是当前编程的主流方法. 1.主Activity    package com.bison;            import android.app.Activity;      import android.content.pm.ActivityInfo;      import android.os.Bundle;      import android.view.Wind