android开发通过Scroller实现过渡滑动效果操作示例

本文实例讲述了android开发通过Scroller实现过渡滑动效果。分享给大家供大家参考,具体如下:

主要介绍一下Scroller这个类,它可以实现过渡滑动的效果,使滑动看起来不是那么生硬,当然它用大量的重绘来实现,invalidate();通过源码看:

看构造方法

 /**
   * Create a Scroller with the default duration and interpolator.
   */
  public Scroller(Context context) {
    this(context, null);
  }
  /**
   * Create a Scroller with the specified interpolator. If the interpolator is
   * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
   * be in effect for apps targeting Honeycomb or newer.
   */
  public Scroller(Context context, Interpolator interpolator) {
    this(context, interpolator,
        context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
  }
  /**
   * Create a Scroller with the specified interpolator. If the interpolator is
   * null, the default (viscous) interpolator will be used. Specify whether or
   * not to support progressive "flywheel" behavior in flinging.
   */
  public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
    mFinished = true;
    if (interpolator == null) {
      mInterpolator = new ViscousFluidInterpolator();
    } else {
      mInterpolator = interpolator;
    }
    mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
    mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
    mFlywheel = flywheel;
    mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
  }

我们用默认的就行,传个context就行了,其他的什么差值器,先不管了

然后调用startScroll,传递我们歧视滑动位置和滑动的偏移量,还有可选的默认持续时间,默认为250毫秒
这个方法是用来赋值的,接下来会调用invalidate()进行重新绘制,然后就会onDraw(),这时候会调用
computeScroll()这个方法,我们重写这个方法,computeScrollOffset()是判断动画有没有结束的一个方法,没结束的时候,我们根据滑动的偏移位置进行移动也就是scrollto到scroller的当前位置,再次调用invalidate(),由此无数的重回进行拼接形成了平滑的滑动

/**
   * Call this when you want to know the new location. If it returns true,
   * the animation is not yet finished.
   */
  public boolean computeScrollOffset() {
    if (mFinished) {
      return false;
    }
    int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
    if (timePassed < mDuration) {
      switch (mMode) {
      case SCROLL_MODE:
        final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
        mCurrX = mStartX + Math.round(x * mDeltaX);
        mCurrY = mStartY + Math.round(x * mDeltaY);
        break;
      case FLING_MODE:
        final float t = (float) timePassed / mDuration;
        final int index = (int) (NB_SAMPLES * t);
        float distanceCoef = 1.f;
        float velocityCoef = 0.f;
        if (index < NB_SAMPLES) {
          final float t_inf = (float) index / NB_SAMPLES;
          final float t_sup = (float) (index + 1) / NB_SAMPLES;
          final float d_inf = SPLINE_POSITION[index];
          final float d_sup = SPLINE_POSITION[index + 1];
          velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
          distanceCoef = d_inf + (t - t_inf) * velocityCoef;
        }
        mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
        mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
        // Pin to mMinX <= mCurrX <= mMaxX
        mCurrX = Math.min(mCurrX, mMaxX);
        mCurrX = Math.max(mCurrX, mMinX);
        mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
        // 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;
  }
 public void startScroll(int startX, int startY, int dx, int dy) {
    startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
  }
 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;
    mDurationReciprocal = 1.0f / (float) mDuration;
  }
public class MoveFreeView extends View{
  private int movedX;
  private int movedY;
  private Scroller mScroller;
  public MoveFreeView(Context context) {
    super(context);
  }
  public MoveFreeView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    mScroller = new Scroller(context);
  }
  public MoveFreeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    //获取触摸点到边界坐标
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()){
      case MotionEvent.ACTION_DOWN:
        movedX = x;
        movedY = y;
        break;
      case MotionEvent.ACTION_MOVE:
        int offsetX = x-movedX;
        int offsetY = y-movedY;
        layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
        break;
    }
    return super.onTouchEvent(event);
  }
  //供外界调用通过传递x,y的的滑动距离
  public void smoothScrollTo(int destinyX,int destinyY){
    //向右侧,下方滑动,请传递负值
    int scrollX = getScrollX();
    int scrollY = getScrollY();
    int delta = destinyX - scrollX;
    int deltaY = destinyY - scrollY;
    mScroller.startScroll(scrollX,scrollY,delta,deltaY,5000);
    invalidate();
  }
  @Override
  public void computeScroll() {
    super.computeScroll();
    //true则表示滑动未结束
    if (mScroller.computeScrollOffset()){
      ((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
      invalidate();
    }
  }
}
private MoveFreeView button;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button = (MoveFreeView) findViewById(R.id.custon);
    button.smoothScrollTo(-400,-300);
    //    button.startAnimation(AnimationUtils.loadAnimation(this,R.anim.translate));
//    ObjectAnimator animtor1 = ObjectAnimator.ofFloat(button, "translationX", 0, 300);
//    ObjectAnimator animtor2 = ObjectAnimator.ofFloat(button, "translationY", 0, 300);
//    ObjectAnimator animator3 = ObjectAnimator.ofFloat(button,"rotationX",0.0f,360f);
//    ObjectAnimator animator4 = ObjectAnimator.ofFloat(button,"scaleX",1.5f,0.5f);
//    AnimatorSet set= new AnimatorSet();
//    set.setDuration(5000);
//    set.playTogether(animtor1,animtor2,animator3,animator4);
//    set.addListener(new Animator.AnimatorListener() {
//      @Override
//      public void onAnimationStart(Animator animator) {
//
//      }
//
//      @Override
//      public void onAnimationEnd(Animator animator) {
//        //动画结束时做一些事情
//      }
//
//      @Override
//      public void onAnimationCancel(Animator animator) {
//
//      }
//
//      @Override
//      public void onAnimationRepeat(Animator animator) {
//
//      }
//    });
//    set.start();
  }
}

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

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

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

  • Android Scroller完全解析

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

  • Android Scroller大揭秘

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

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

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

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

    本文实例为大家分享了Android使用Scroller实现弹性滑动展示的具体代码,供大家参考,具体内容如下 scrollTo.scrollBy View内部为了实现滑动提供了这两个方法,但是使用这两个方法滑动的效果是瞬间的不够平滑,如何实现View的弹性滑动呢?这正是本博文讨论的主题.另外这两个函数滑动的是View的内容不是View本身.比如对于普通View好比TextView其内容就是文本,ImageView的内容则是drawable对象,采用这两种方法滑动的时候其实分别滑动的是文本及draw

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

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

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

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

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

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

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

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

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

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

随机推荐