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方法的目的从而实现平滑滑动。

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

(0)

相关推荐

  • 详解Android Scroller与computeScroll的调用机制关系

    Android ViewGroup中的Scroller与computeScroll的有什么关系? 答:没有直接的关系 知道了答案,是不是意味着下文就没必要看了,如果说对ViewGroup自定义控件不感兴趣,可以不用看了. 1.Scroller到底是什么? 答:Scroller只是个计算器,提供插值计算,让滚动过程具有动画属性,但它并不是UI,也不是滑动辅助UI运动,反而是单纯地为滑动提供计算. 无论从构造方法还是其他方法,以及Scroller的属性可知,其并不会持有View,辅助ViewGrou

  • Android Scroller及下拉刷新组件原理解析

    Android事件拦截机制 Android中事件的传递和拦截和View树结构是相关联的,在View树中,分为叶子节点和普通节点,普通节点有子节点只能是ViewGroup,叶子节点可以是View或者ViewGroup.Android和事件分发拦截相关的方法有 dispatchTouchEvent(MotionEvent ev) 事件分发相关的方法,沿着View树将一个用户的触摸事件向下分发. onInterceptTouchEvent(MotionEvent ev) 在dispatchTouchE

  • Android Scroller大揭秘

    在学习使用Scroller之前,需要明白scrollTo().scrollBy()方法. 一.View的scrollTo().scrollBy() scrollTo.scrollBy方法是View中的,因此任何的View都可以通过这两种方法进行移动.首先要明白的是,scrollTo.scrollBy滑动的是View中的内容(而且还是整体滑动),而不是View本身.我们的滑动控件如SrollView可以限定宽.高大小,以及在布局中的位置,但是滑动控件中的内容(或者里面的childView)可以是无

  • Android Scroller完全解析

    在Android中,任何一个控件都是可以滚动的,因为在View类当中有scrollTo()和scrollBy()这两个方法,如下图所示: 这两个方法的主要作用是将View/ViewGroup移至指定的坐标中,并且将偏移量保存起来.另外: mScrollX 代表X轴方向的偏移坐标 mScrollY 代表Y轴方向的偏移坐标 这两个方法都是用于对View进行滚动的,那么它们之间有什么区别呢?简单点讲,scrollBy()方法是让View相对于当前的位置滚动某段距离,而scrollTo()方法则是让Vi

  • 详解Android应用开发中Scroller类的屏幕滑动功能运用

    今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与scrollBy这两个函数的区别 .   首先 ,我们必须明白在Android View视图是没有边界的,Canvas是没有边界的,只不过我们通过绘制特定的View时对Canvas对象进行了一定的操作,例如 : translate(平移).clipRect(剪切)等,以便达到我们的对该Canvas对象绘制的要求 ,我们可以将这种无边界的视图称为"视图坐标"----

  • Android用Scroller实现一个可向上滑动的底部导航栏

    静静等了5分钟竟不知道如何写我这第一篇文章.每次都想好好的学习学习,有时间多敲敲代码,写几篇自己的文章.今天终于开始实行了,还是有点小激动的.哈哈! 好了废话就不多收了.我今天想实现的一个功能就是一个可以上滑底部菜单栏.为什么我会想搞这么个东西呢, 还是源于一年前,我们app 有这么个需求,当时百度也好谷歌也好,都没有找到想要的效果,其实很简单的一个效果.但是当时我也是真的太菜了,所有有关自定义的控件真的是不会,看别人的代码还好,真要是自己写,一点头绪都没有.因为我试着写了,真的不行啊.当时觉得

  • android使用 ScrollerView 实现 可上下滚动的分类栏实例

    如果不考虑更深层的性能问题,我个人认为ScrollerView还是很好用的.而且单用ScrollerView就可以实现分类型的RecyclerView或ListView所能实现的效果. 下面我单单从效果展示方面考虑,使用ScrollerView实现如下图所示的可滚动的多条目分类,只是为了跟大家一起分享一下新思路.(平时:若从复用性等方面考虑,这显然是存在瑕疵的~) 特点描述: 1.可上下滚动 2.有类似于网格布局的样式 3.子条目具有点击事件 刚看到这个效果时,首先想到的是使用分类型的Recyc

  • Android程序开发之UIScrollerView里有两个tableView

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UIViewController <UIScrollViewDelegate,UITableViewDelegate,UITableViewDataSource> { UIScrollView *_scrolView; UITableView *_tableView; UITableView

  • 深入理解Android中Scroller的滚动原理

    View的平滑滚动效果 什么是实现View的平滑滚动效果呢,举个简单的例子,一个View从在我们指定的时间内从一个位置滚动到另外一个位置,我们利用Scroller类可以实现匀速滚动,可以先加速后减速,可以先减速后加速等等效果,而不是瞬间的移动的效果,所以Scroller可以帮我们实现很多滑动的效果. 首先我们先来看一下Scroller的用法,基本可概括为"三部曲": 1.创建一个Scroller对象,一般在View的构造器中创建: public ScrollViewGroup(Cont

  • Android自定义View弹性滑动Scroller详解

    本文实例为大家分享了Android弹性滑动类Scroller的具体代码,供大家参考,具体内容如下 Scroller是什么 Scroller就是一个滑动帮助类.它并不可以使View真正的滑动,而是配合scrollTo/ScrollBy让view产生缓慢的滑动,产生动画的效果,其实和属性动画是同一个原理.在我看来,Scroller跟属性动画的平移的效果是一样的. 如何使用 //①实例一个Scroller,它有三个构造方法如下 //public Scroller (Context context) /

随机推荐