Android使用Scroller实现弹性滑动效果

 更新时间:2022年04月18日 15:58:42   作者:钟离四郎  
这篇文章主要介绍了Android使用Scroller实现弹性滑动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android使用Scroller实现弹性滑动展示的具体代码,供大家参考,具体内容如下

scrollTo、scrollBy

View内部为了实现滑动提供了这两个方法,但是使用这两个方法滑动的效果是瞬间的不够平滑,如何实现View的弹性滑动呢?这正是本博文讨论的主题。另外这两个函数滑动的是View的内容不是View本身。比如对于普通View好比TextView其内容就是文本,ImageView的内容则是drawable对象,采用这两种方法滑动的时候其实分别滑动的是文本及drawable对象,对于ViewGroup采用这两种方法滑动的时候则是对其子元素的滑动。所以想要使用scrollTo、scrollBy方法实现拖动View(指的是普通的View不包含ViewGroup)的效果必须在View外面在包一层ViewGroup。

Scroller类

上面提到使用scrollTo、scrollBy来滑动View的时候是很生硬得滑过去的,不够平滑,自然用户体验也不好,因此我们要实现一个弹性的滑动。如何实现弹性滑动呢?方法有很多,但思想都是一致的,即将实现一段距离的滑动分成多次来进行,每一次滑动一小段,渐近式的滑动。本文只是介绍其中的一种即使用Scroller实现弹性滑动。以下结合实例看看Scroller是如何实现平滑滑动的呢 ?

public class SmoothScrollView extends LinearLayout{ 
 
  Scroller mScroller ; 
  int startX; 
  int startY; 
public SmoothScrollView(Context context, AttributeSet attrs) { 
  super(context, attrs); 
  //创建Scroller实例 
  mScroller = new Scroller(context); 
  } 
 
 
public void smoothScroll(int dx,int dy,int duration){ 
  //获取滑动起点坐标 
  startX = getScrollX(); 
  startY = getScrollY(); 
  //设置滑动参数 
  mScroller.startScroll(startX,startY,dx,dy,duration); 
  //重新绘制View 
  invalidate(); 
  } 
 
@Override 
public void computeScroll() { 
  // TODO Auto-generated method stub 
  super.computeScroll(); 
  boolean flag = mScroller.computeScrollOffset(); 
  //递归终止条件:滑动结束 
  if(flag == false){ 
    return; 
  }else{ 
  //mScroller.getCurrX(),mScroller.getCurrY()记录的是此刻要滑动达到的目标坐标 
  scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); 
  } 
  //递归调用 
  invalidate();//或者postInvalidate() 
  } 
} 

 看到第9行,首先在SmoothScrollView内部创建一个Scroller对象,第13行的smoothScroll方法是实现SmoothScrollView的平滑滑动,可以看到实现平滑滑动首先调用第18行Scroller的startScroll方法来设置滑动参数,下文会分析这个方法,这里先放一放。然后在第20行调用invalidate方法,这个方法会导致SmoothScrollView重绘,从而调用draw方法之后又会调用computeScroll方法,在第24行可以看到这里重写了computeScroll方法,因此调用invalidate方法最终会导致computeScroll方法被调用。第27~29行调用Scroller的computeScrollOffeset方法并判断是否滑动结束,computeScrollOffset是如何判断滑动结束的呢?这里也先放一放下文在分析。如果滑动未结束,执行第33行调用scrollTo滑动SmoothScrollView至此刻目的坐标,然后递归调用invalidate方法。

以下是对Scroller几个方法的分析:

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; 
  //mDuration表示的是整个滑动持续的时间 
    mDurationReciprocal = 1.0f / (float) mDuration; 
  } 

从以上代码可以看到startScroll方法其实根本没有滑动View只是对滑动参数进行设置。往下再来看看computeScrollOffset方法,computeScrollOffset返回true则表示滑动还没结束返回false表示滑动结束,它的实现如下:
[java] view plain copy

public boolean computeScrollOffset() { 
    if (mFinished) { 
      return false; 
    } 
 
    int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 
   //判断此刻是否在有效滚动周期内 
    if (timePassed < mDuration) { 
      switch (mMode) { 
      case SCROLL_MODE: 
  //当前时刻滑动偏移量所占份额 
        float x = (float)timePassed * mDurationReciprocal; 
   
        if (mInterpolator == null) 
          x = viscousFluid(x);  
        else 
          x = mInterpolator.getInterpolation(x); 
        //获取当前时刻要滚动到的位置 
        mCurrX = mStartX + Math.round(x * mDeltaX); 
        mCurrY = mStartY + Math.round(x * mDeltaY); 
        break; 
      case FLING_MODE: 
        float timePassedSeconds = timePassed / 1000.0f; 
        float distance = (mVelocity * timePassedSeconds) 
            - (mDeceleration * timePassedSeconds * timePassedSeconds / 2.0f); 
         
        mCurrX = mStartX + Math.round(distance * mCoeffX); 
        // Pin to mMinX <= mCurrX <= mMaxX 
        mCurrX = Math.min(mCurrX, mMaxX); 
        mCurrX = Math.max(mCurrX, mMinX); 
         
        mCurrY = mStartY + Math.round(distance * mCoeffY); 
        // Pin to mMinY <= mCurrY <= mMaxY 
        mCurrY = Math.min(mCurrY, mMaxY); 
        mCurrY = Math.max(mCurrY, mMinY); 
 
        if (mCurrX == mFinalX && mCurrY == mFinalY) { 
          mFinished = true; 
        } 
 
        break; 
      } 
    } 
    else { 
      mCurrX = mFinalX; 
      mCurrY = mFinalY; 
      mFinished = true; 
    } 
    return true; 
  } 
   

看到这我们应该明白SmoothScrollView是如何实现让自己平滑滑动的呢?实际上正真让SmoothScrollView产生平滑滑动的并非是Scroller而是SmoothScrollView自己,是SmoothScrollView自己多次调用了自己的scrollerTo方法并且每次滑动一小步从而实现平滑滑动,而Scroller类干的事只是辅助SmoothScrollView计算每一次小滑动要到达的目标坐标,而实现多次调用了自己的scrollerTo方法这里没有使用循环体则是利用程序设计技巧“递归调用”invalidate方法达到多次调用scrollTo方法的目的从而实现平滑滑动。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈android性能优化之启动过程(冷启动和热启动)

    浅谈android性能优化之启动过程(冷启动和热启动)

    本篇文章主要介绍了浅谈android性能优化之启动过程(冷启动和热启动) ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-08-08
  • 详解Android中motion_toast的使用

    详解Android中motion_toast的使用

    我们通常会用 toast(也叫吐司)来显示提示信息,例如网络请求错误,校验错误等等。本文为大家介绍一个非常有趣的toast组件 —— motion_toast,感兴趣的可以了解一下
    2022-06-06
  • Android Jetpack组件Navigation导航组件的基本使用

    Android Jetpack组件Navigation导航组件的基本使用

    本篇主要简单介绍了一下 Navigation 是什么 以及使用它的流程是什么,并且结合实际案例 操作了一番,Navigation 还有很多其他用法,如条件导航、嵌套图、过度动画 等等功能 有机会再操作,需要的朋友可以参考下
    2022-06-06
  • Android系统的五种数据存储形式实例(一)

    Android系统的五种数据存储形式实例(一)

    Android系统有五种数据存储形式,分别是文件存储、SP存储、数据库存储、contentprovider 内容提供者、网络存储。本篇文章详解的介绍了每种数据存储的用法,有兴趣的可以了解一下。
    2016-12-12
  • Android中的图片优化完全指南

    Android中的图片优化完全指南

    这篇文章主要给大家介绍了关于Android中图片优化的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Android使用记录访问权限详解

    Android使用记录访问权限详解

    这篇文章主要介绍了Android使用记录访问权限的相关资料,文中介绍的很详细,对大家具有一定的参考借鉴价值,需要的朋友们下面来一起看看吧。
    2017-02-02
  • Android中Fragment的基本用法示例总结

    Android中Fragment的基本用法示例总结

    Fragment是activity的界面中的一部分或一种行为,下面这篇文章主要给大家介绍了关于Android中Fragment的基本用法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-05-05
  • Android键盘自动弹出解决方法分析

    Android键盘自动弹出解决方法分析

    这篇文章主要介绍了Android键盘自动弹出解决方法,结合实例形式对比分析了三种解决方法,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-01-01
  • 浅析Android企业级开发数据绑定技术

    浅析Android企业级开发数据绑定技术

    这篇文章通过代码实例分析了Android企业级开发数据绑定技术的应用以及相关的原理知识,跟着小编一起学习参考下吧。
    2017-12-12
  • Android消息通知栏的实现方法介绍

    Android消息通知栏的实现方法介绍

    本篇文章是对Android消息通知栏的实现方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06

最新评论