Deep understanding of the rolling principle of scroller in Android _android

Source: Internet
Author: User

Smooth scrolling effect of view

What is the realization of the smooth scrolling effect of view, for example, a view from the time we specify from one position to another position, we use the Scroller class can be used to achieve uniform rolling, can be accelerated after deceleration, can first slow down after acceleration and so on, Instead of the instantaneous movement of the effect, so scroller can help us achieve a lot of sliding effect.

First, let's take a look at the usage of scroller, which can be summed up as "the trilogy":

1. Create a Scroller object, typically created in the view's constructor:

Public Scrollviewgroup {This
  (context, NULL);
}

Public Scrollviewgroup (context, AttributeSet attrs) {This
  (context, attrs, 0);
}

Public Scrollviewgroup (context, AttributeSet attrs, int defstyleattr) {
  Super (context, Attrs, defstyleattr );
  Mscroller = new Scroller (context);

2, rewrite the view of the Computescroll () method, the following code is basically unchanged:

@Override public
void Computescroll () {
  super.computescroll ();
  if (Mscroller.computescrolloffset ()) {
    Scrollto (Mscroller.getcurrx (), Mscroller.getcurry ());
    Postinvalidate ();
  }

3, call the Startscroll () method, StartX and Starty for the start scrolling coordinate point, dx and dy for the corresponding offset:

Mscroller.startscroll (int startx, int starty, int dx, int dy);
Invalidate ();

The three steps above are the basic usage of scroller.

The next task is to parse the rolling principle of scroller.

And before that, we have one more thing to do, and that's the principle of figuring it out scrollTo() scrollBy() . scrollTo()and scrollBy() The difference here I do not repeat the narrative, do not understand can be Google or Baidu.

scrollTo()The following source code is posted:

public void Scrollto (int x, int y) {
  if (mscrollx!= x | | mscrolly!= y) {
    int oldx = MSCROLLX;
    int oldy = mscrolly;
    MSCROLLX = x;
    mscrolly = y;
    Invalidateparentcaches ();
    Onscrollchanged (MSCROLLX, mscrolly, OLDX, oldy);
    if (!awakenscrollbars ()) {
      postinvalidateonanimation ();}}}

When it is set up mScrollX and mScrollY then invoked, the view is redrawn onScrollChanged(mScrollX, mScrollY, oldX, oldY);  . This will achieve the effect of sliding.

Let's take a look at the following scrollBy() :

public void Scrollby (int x, int y) {
  Scrollto (mscrollx + x, mscrolly + y);
}

Such a brief code is believed that we all understand, originally scrollBy() internal is called scrollTo() . But scrollTo() / scrollBy() the scrolling is instantaneous, how to achieve smooth scrolling.

I don't know if you have any idea: if we divide the offset to be a few small offsets, of course, this is a big amount. Then use scrollTo() / scrollBy() each time to scroll the offset of the small part. In a certain amount of time, does it become smooth scrolling? Yes, Scroller is using this principle to achieve smooth scrolling.

Below we take a look at the source code bar!

According to the first part of the trilogy, let's look at the Scroller constructor:

Public Scroller (context context, Interpolator interpolator, Boolean flywheel) {
  mfinished = true;
  if (interpolator = = null) {
    minterpolator = new Viscousfluidinterpolator ();
  } else {
    minterpolator = Interpol Ator;
  }
  Mppi = Context.getresources (). Getdisplaymetrics (). density * 160.0f;
  Mdeceleration = Computedeceleration (Viewconfiguration.getscrollfriction ());
  Mflywheel = flywheel;

  Mphysicalcoeff = Computedeceleration (0.84f); Look and feel tuning
}

The main thing to do in the constructor is to specify the interpolation, and if no interpolation is specified, use the default ViscousFluidInterpolator .

Let's take a look at Scroller's startScroll() :

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;
}

We found that it startScroll() didn't start scrolling, but instead set the initial value of a bunch of variables, so what exactly is it that makes the view start rolling? We should concentrate our goals on startScroll() the next sentence invalidate(); . We can understand this: first startScroll() set up a bunch of initial values, then call invalidate(); let view redraw, here is another important point, in the draw() call computeScroll() this method!

The source code is too long, here is not posted. Want to see the children's shoes in the view class search boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) This method can be seen. ViewGroup.drawChild()the method of the child view is invoked by means of the method draw() . And in the view class computeScroll() is an empty method that we need to implement:

/**
 * Called by a parent to request this a child update its values for MSCROLLX
 * and mscrolly if necessary. This would typically be done if the child is
 * animating a scroll using a {@link Android.widget.Scroller scroller}
 * Object.
 *
/public void Computescroll () {
}

And in the second part of the "trilogy" above, we have already achieved it computeScroll() . First of all computeScrollOffset() , let's take a look at the relevant source code:

/** * Call this is 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.getinterpo
      Lation (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; }

The return value of this method is fastidious, and if true it means that the sliding of the scroller is not over; if false, the slip of the scroller is over. Then look at the internal code: first calculated the time has been sliding, if the time has been sliding less than the total sliding time, it is not the end of the slide; mFinished = true;  And in the sliding is not over to be divided into two mode, but these two mode have done the same thing, roughly is based on the time timepassed and interpolation to calculate the distance and the point of scrolling mCurrX mCurrY . mScroller.getCurrX()  the value of the second part of the "trilogy" above mScroller.getCurrY() .

The method is then called in the second section scrollTo() to scroll to the specified point (that is mCurrX , above mCurrY ). It is then called postInvalidate(); , so that the view is redrawn and called back computeScroll() in this loop until the view scrolls to the specified position, and the scroller scroll ends.

In fact, the principle of scroller is still relatively easy to understand. Let's figure out a way to end today's scroller resolution in the form of a picture:

Summarize

OK, this article describes the scroller of Android in the rolling principle of the content to this end, if you have any questions can be in the following message. Hopefully this article will help you develop Android.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.