0. 前言  

欢迎转载,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52538723

我们在Android开发——View滑动的三种实现方式中学习了如何进行View滑动,在第一种方法,利用ScrollBy和ScrollTo进行滑动时,滑动效果是瞬间完成的,为了更好的用户体验,有时我们需要滑动有一个渐变的过程。这就是所谓的弹性滑动。

1.   延时策略

我们解决弹性滑动的第一反应可能就是采用延时策略,通过Handler发送并接收延时消息,每次接收到消息便完成一次ScrollTo操作,从而实现弹性滑动的效果。核心代码展示如下:

public void handleMessage(Message msg) {
switch(mag.what){
case SCROLL_FRACTION:{
//if判断滑动还没有结束,结束则不再滑动和发送消息
if(){
//通过滑动完成比例计算该次滑动片段的位置点scrollX,scrollY
View.scrollTo(scrollX,scrollY);
mHandler.sendEmptyMessageDelayed(SCROLL_FRACTION, 20);
}
break;
}
default:
break;
}
}

上述这种利用Handler发送延时消息的方式比较简单,但是需要注意的是,由于系统的消息调度需要时间,完成这次弹性滑动的时间总是大于if条件判断为true的次数乘以20ms(延迟消息的发送时间间隔)。

因此对弹性滑动完成总时间有精确要求的使用场景下,使用延时策略是一个不太合适的选择。

2.  Scroller的使用

2.1  系统提供的Scroller

利用系统提供给我们的Scroller类,我们可以很方便的实现弹性滑动。代码比较简单,都是模版化的,如下所示:

Scroller scroller = new Scroller(mContext);
private void smoothScrollTo(int destX, int destY){
int distanceX = destX - getScrollX();
int distanceY = destY - getScrollY();
//设置500ms的弹性滑动总时长
mScroller.startScroll(getScrollX(),getScrollY(),distanceX, distanceY, 500);
//重绘
invalidate();
}
//该方法为空实现,因此需要重写
//该方法会被invalidate()方法触发执行
@override
public void computeScroll(){
//判断滑动还没有结束
if(mScroller.computeScrollOffset()){
//通过Scroller类拿到下一步要滑动到的位置
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}

这里说一下invalidate()和postInvalidate()的区别:

为了UI安全,invalidate()可在主线程直接调用刷新界面,而postInvalidate()会用Handler通知UI线程重绘屏幕,因此后者适用于子线程。

2.2  自定义Scroller

上面介绍了调用系统提供的Scroller的使用方法,但是Scroller类的getCurrX()、computeScrollOffset()等方法都是写死的。实现的弹性滑动是先快后慢的效果。

下面我们自行实现一个MyScroller类来完成匀速滑动的效果,同时也有助于理解系统Scroller类的实现原理。

/*
* Created by SEU_Calvin on 2016/09/12
* 计算位移距离的自定义Scroller
*/
public class MyScroll{
private int startX;
private int startY;
private int distanceX;
private int distanceY;
private int duration;
//开始执行动画的时间
private long startTime;
//判断是否动画结束
private boolean isFinish;
//计算当前距离
private long currentX;
private long currentY;
public MyScroll(Context context) {
} public long getCurrX() {
return currentX;
}
public long getCurrY() {
return currentY;
} public void startScroll(int startX, int startY, int distanceX, int distanceY, int duration) {
this.startX = startX;
this.startY = startY;
this.distanceX = distanceX;
this.distanceY = distanceY;
this.duration = duration;
this.startTime = SystemClock.uptimeMillis();
this.isFinish = false;
}
/*
* Created by SEU_Calvin on 2016/09/12
* 判断是否滑动结束并改变将要被使用的currentX/Y
*/
public boolean computeScrollOffset() {
if(isFinish){
return false;
}
//获得startTime到调用由于重绘导致computeScrollOffset()调用之间的passtime
long passtime = SystemClock.uptimeMillis()-startTime;
//计算currentX的值,指导下一步ScrollTo的位置
//startX/Y <currentX/Y<= startX/Y + distanceX/Y
if(passtime<duration){
currentX = startX + distanceX*passtime/duration;
currentY = startY + distanceY*passtime/duration;
}else{
//运行结束
currentX = startX + distanceX;
currentY = startY + distanceY;
isFinish = true;
}
return true;
}
}

我们只要在调用时改变调用的MyScroll类即可。其他代码不做修改。

具体滑动效果,如匀速,匀加速,先慢后快等效果完全可以由MyScroll中自己的算法来决定。

以上就是对Android开发中弹性滑动的介绍。

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52538723

Android开发——弹性滑动的两种实现方式的更多相关文章

  1. Android中BroadcastReceiver的两种注册方式(静态和动态)详解

    今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...

  2. android位移动画的两种实现方式

    在android开发,我们会常常使用到位移动画,普通情况下位移动画有两种实现方式.一种是直接通过java代码去实现,第二种是通过配置文件实现动画,以下是两种动画的基本是用法: 纯Java代码实现: / ...

  3. android旋转动画的两种实现方式

    在android开发,我们会常常使用到旋转动画,普通情况下旋转动画有两种实现方式,一种是直接通过java代码去实现,第二种是通过配置文件实现动画.以下是两种动画的基本是用法: 纯Java代码实现: / ...

  4. Android传递Bitmap的两种简单方式及其缺陷

    Android传递Bitmap的几种简单方式 一,通过Intent的Bundle. 比如有两个activity,A,B,从A进入B.先在A中将Bitmap写进去: Resources res=getR ...

  5. Android中Fragment的两种创建方式

    fragment是Activity中用户界面的一个行为或者是一部分.你可以在一个单独的Activity上把多个Fragment组合成为一个多区域的UI,并且可以在多个Activity中再使用.你可以认 ...

  6. android中的OnClickListener两种实现方式

    android的activity点击事件中,通过OnClickListener来实现,要实现点击事件有两种方式 1.通过定义一个OnClickListener的内部类来实现 The example b ...

  7. android textView 添加超链接(两种实现方式)

    在textView添加超链接,有两种方式,第一种通过HTML格式化你的网址,一种是设置autolink,让系统自动识别超链接,下面为大家介绍下这两种方法的实现 在textView添加超链接,有两种方式 ...

  8. android 定时请求(两种实现方式)

    方式一: Handler + Runnable (借鉴网址:http://stackoverflow.com/questions/6207362/how-to-run-an-async-task-fo ...

  9. Android中Fragment与Activity之间的交互(两种实现方式)

    (未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...

随机推荐

  1. 解决圆角bitmap保存时背景为黑色

    1.cropBitmap.copy(Bitmap.Config.ARGB_8888, true);cropBitmap.compress(Bitmap.CompressFormat.PNG, 100, ...

  2. StringBuffer和StringBuilder区别?

    1. String是不可变类,改变String变量中的值,相当于开辟了新的空间存放新的string变量 2. StringBuffer 可变的类,可以通过append方法改变变量的值,且StringB ...

  3. jQuery-prepend、append、before、after的区别

    举例说明,原始html代码如下: <ol> <li>List item 1</li> <li>List item 2</li> <li ...

  4. 笨办法学Python(三十六)

    习题 36: 设计和调试 现在你已经学会了“if 语句”,我将给你一些使用“for 循环”和“while 循环”的规则,一面你日后碰到麻烦.我还会教你一些调试的小技巧,以便你能发现自己程序的问题.最后 ...

  5. 使用ABAP代码创建S/4HANA里的Sales Order

    下图是使用ABAP代码创建的S/4HANA的Sales Order的截图: 其中红色区域的值是我代码里硬编码的,而蓝色是函数SD_SALESDOCUMENT_CREATE自己创建的. 来看下代码: D ...

  6. webpack-dev-server启动后, localhost:8080返回index.html的原理

    webpack-dev-server是一个采用Node.js Express实现的微型服务器, 内部使用webpack-dev-middleware来响应发送到服务器监听单口的HTTP请求. webp ...

  7. 使用selenium 检测js报错

    背景:接到一个需求,想检测页面是否能检测js报错,何为js报错,如下图所示,在控制台中,使用console,如果有js报错,就会出现错误 如何检测,简单版操作,打开一个url,使用manage获取浏览 ...

  8. gearman安装实录

    花了5个小时装好了gearman,问题不断,坑爹的服务器yum还坏了,悲催. 服务器系统:centos5.3 64位 gearman版本:1.1.8 安装包(相关依赖)下载 1.gearman安装包 ...

  9. P1567 统计天数

    题目背景 统计天数 题目描述 炎热的夏日,KC非常的不爽.他宁可忍受北极的寒冷,也不愿忍受厦门的夏天.最近,他开始研究天气的变化.他希望用研究的结果预测未来的天气. 经历千辛万苦,他收集了连续N(1& ...

  10. 2017.9.24 JSP动态页面

    1.1 JSP(Java Server Page)是一种运行在服务器端的脚本语言,用来开发动态网页的开发技术. 1.2 JSP页面的结构 JSP页面主要由HTML和JSP代码构成,JSP代码是通过&q ...