欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-03-04 17:01:33
本文实例讲述了android开发通过scroller实现过渡滑动效果。分享给大家供大家参考,具体如下: 主要介绍一下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();
  }
}