Android Custom Viewpager (i)--custom scroller simulation animation process

Source: Internet
Author: User

Reprint Please specify source:http://blog.csdn.net/allen315410/article/details/41575831

I believe that the Android SDK provides the Viewpager components, we are really familiar with, But Viewpager exists under the SUPPORT.V4 package, stating that Viewpager does not exist in earlier versions of Android, so how do you use Viewpager-like sliding effects in earlier versions of Android? Here, we will continue to explore the Andrid custom components well, and this blog only to explore some of the knowledge of Android, not deliberately to build a custom Viewpager to use, this is not necessary, please focus on the realization of this effect of the knowledge point, convenient later "Extrapolate".

OK, let's start with a brief analysis of Viewpager. Viewpager can be seen as a "container" in which a wide variety of view types can be placed, such as Viewpager on each page of a textview,imageview,listview, GridView and so on a series of view components, in fact, these view on the Viewpager of the layout we can be seen on the viewgroup of the various view (in fact, this implementation is more complex, here is a metaphor), So we can abstractly understand that Viewpager is equivalent to ViewGroup, and layout various view on this viewgroup, so in the next code, we need a custom viewgroup to achieve this effect. In addition, it is necessary to add a left and right sliding effect on the view on each page of the ViewGroup, in order to simulate the dynamic effect on the Viewpager.

With regard to the structure of custom viewgroup, it is necessary to take a closer look at some of the concepts that are worth understanding, and for ease of understanding, see "Sketches" below:


As can be seen from the above sketch, the red border represents the device screen, where we can see with the naked eye, the entire gray border represents the entire effect, here is called "view", each view is divided into 3 views, this 3 or more view form a large view. We need to figure out the relationship between the three, the display area represented by the device screen, which is the range we see on the device, the view represents a single component, one screen can display one or more views, but the view is the most confusing thing, the view is theoretically a large area, It includes not only a part of the device's screen that can be seen by the naked eye, but also a place invisible to the naked eye outside the device's screen, as shown in the sub-View2 and sub-View3 are also part of the view, but outside the device screen, it is invisible to the naked eye. Views can be stored in a view that is used to manage the view's display. Moreover, the view is free to move, and by controlling the view's activity and controlling the view's display on the device screen, you can switch between different pagination.

So what we're going to do is to customize a view, how to make the view show different views on the device screen, manage multiple view displays on Android, and customize the ViewGroup for OnLayout to view. When I initialized the layout, I added 6 sub-view to the ViewGroup, the 6 sub-view is horizontal horizontal layout, as shown, each view display width and height is the same as the parent view (ViewGroup), the first layout renders the first child view on the screen , the other 5 sub-views are added in times, and are formatted with n multiples of the width of the parent view, and are hidden in the right area of the device screen. Here is the implementation code for the custom ViewGroup:

Package Com.example.myviewpager;import Android.content.context;import Android.util.attributeset;import Android.view.gesturedetector;import Android.view.motionevent;import Android.view.view;import Android.view.viewgroup;public class Myviewpager extends ViewGroup {/** gesture recognizer */private gesturedetector detector;/** Context * /private context ctx;/** The coordinates of the x-axis for the first time */private int firstdownx;/** record the ID of the current view */private int currid = 0;/** Simulation Animation tool */privat E myscroller myscroller;public Myviewpager (context context, AttributeSet Attrs) {Super (context, attrs); this.ctx = Context;init ();} private void Init () {Myscroller = new Myscroller (CTX);d etector = new Gesturedetector (ctx,new Gesturedetector.ongesturelistener () {@Overridepublic Boolean onsingletapup (Motionevent e) {return false;} @Overridepublic void Onshowpress (Motionevent e) {} @Overridepublic boolean onscroll (motionevent E1, Motionevent e2,float Distancex, float Distancey) {//Finger swipe Scrollby ((int) Distancex, 0); return false;} @Overridepublic void Onlongpress (MOtionevent e) {} @Overridepublic boolean onfling (motionevent E1, motionevent e2,float Velocityx, float velocityy) {return F Alse;} @Overridepublic Boolean Ondown (Motionevent e) {return false;}}); /** * Layout The Sub view to determine the location of the child view changed if True, * indicates that the layout has changed l\t\r\b refers to the location of the current view in the parent view */@Overrideprotected void OnLayout (bool EAN changed, int l, int t, int r, int b) {for (int i = 0; i < Getchildcount (); i++) {View view = Getchildat (i);//Specify Sub VI The position of EW, left, top, right, and bottom, refers to the position in the ViewGroup coordinate system view.layout (0 + i * getwidth (), 0, getwidth () + i * getwidth (), getheight ());}} @Overridepublic boolean ontouchevent (Motionevent event) {detector.ontouchevent (event);//Specify gesture recognizer to handle sliding events// Still have to deal with some logic switch (event.getaction ()) {case Motionevent.action_down://press FIRSTDOWNX = (int) event.getx (); break;case Motionevent.action_move://Mobile Break;case MOTIONEVENT.ACTION_UP://lift int nextid = 0; Record the next view of the Idif (Event.getx ()-firstdownx > GetWidth ()/2) {//finger-off point x-axis coordinate-firstdownx > Half of screen width, left shift NextID = (CurrI d-1) <= 0? 0 : CurrId-1;} else if (Firstdownx-event.getx () > GetWidth ()/2) {//finger left point x coordinate-firstdownx < half of screen width, right shift NextID = Currid + 1;} E LSE {NextID = Currid;} Movetodest (NextID); break;default:break;} return true;} /** * Control the movement of the view * * @param nextid */private void movetodest (int nextid) {//NextID reasonable range is NextID >=0 && nextid &L t;= getchildcount () -1currid = (nextid >= 0)? Nextid:0;currid = (NextID <= getchildcount ()-1)? NextID: (Getchildcount ()-1);//view move, too direct, no dynamic process//ScrollTo (Currid * getwidth (), 0);//distance to move = final position-current position int distance X = Currid * getwidth ()-GETSCROLLX ();//Set Run time Myscroller.startscroll (GETSCROLLX (), 0, Distancex, 0);//Refresh View invalidate ( );} /** * Invalidate (); Causes the execution of this method */@Overridepublic void Computescroll () {if (Myscroller.computeoffset ()) {int newx = (int) my Scroller.getcurrx (); System.out.println ("Newx::" + newx); ScrollTo (newx, 0); invalidate ();}}}

1, the above is the custom ViewGroup all the source code, then we slowly analyze the implementation process, the first is the initialization of the various sub-view layout, the above has been said, the main code in the OnLayout () method has been reflected, relatively simple.

2, realize gesture sliding effect. As we all know, Viewpager can change different pagination as the finger slides on the screen, and in order to achieve the same effect, I override the Ontouchevent (Motionevent event) method of the parent class in the custom ViewGroup. This method is used to handle the logic of sliding events. But for the sake of brevity, I used the gesture recognizer Gesturedetector, using this finger recognizer to manipulate the effect that the view moves with the finger while the finger is moving on the screen, simply in the Gesturedetector onscroll () method, Pass the moved distance to Scrollby (int) as an argument.

3, handle the more complicated finger press down to lift, view toggle. This is a detailed analysis of the process, the following is the process involved in the "sketch":


Here, we use the sub-View2 view as an example to analyze 3 scenarios:

(1), the x-axis coordinate of the finger to leave the point-the finger presses the x axis coordinates of the point > the screen width half, moves left, the screen displays the next view

(2), the x-axis coordinate of the finger to leave the point-the finger presses the x axis coordinates of the point < the screen width half, moves right, the screen displays the previous view

(3), the above two conditions are not satisfied, then stay on the current view, do not switch before and after the view

4, through (3) of the process, we know the current view to which one of the view direction moved, the next need to display the ID of the view, the ID is the ID of the current view, and then the next need to display the id*view width of the view, passed to Scrollto ( int,0) as a parameter to control the movement of the view.

5, through the above steps, the view view of the switch has been completed, but there is a problem, the view of the left and right switch using the Scrollto (Int,int) method, this method to move the view directly to the specified position, but the whole process of moving too fast, A moment to complete the view of the switch, so the experience is very poor, then how can we improve the experience effect? Yes, it is in this view of the switch to a slow process, so that the process of view switching slow or constant speed, so that the experience effect is raised up, then how to change the process of adding a constant speed of the effect of the switch? We might as well start by following a small example to make it easy to understand:

If, there is a personal small A to go through a 100-meter path, he can slowly walk the past, a lot of time, but also can run the past, the time is very short, but he would like to take a leisurely pace of the speed of the path, how to do? At this time he found an engineer small B, let the engineer small B in the side to help him calculate the distance, small a in advance to ask the Engineer small B, the next 5 seconds, I want to walk how many meters ah? Engineer Small B began to calculate the results, and told small A, you advance 10 meters well, when the small a walk through this 10 meters away, small A and asked small B, the next 5 seconds I will advance how many meters distance? Small B A meal calculation, told small a forward 20 meters well, so small a continue to advance 20 meters, stop to ask small b ... Repeat this process and know that little A has gone through the 100-metre path.

The above example is not difficult to understand! So, in the view of the switching process, we also need such an "engineer" time to calculate the displacement within a certain time interval, passed to the view view, the views to get this displacement, immediately moved to the corresponding position, again request "engineer" calculation, the next time interval of the movement of the move, and so on. Below, is our custom to calculate the displacement of the tool class source code:

Package Com.example.myviewpager;import android.content.context;import android.os.systemclock;/** * Tool class for calculating view offsets * * @ Author Administrator * */public class Myscroller {/** start x coordinate */private int startx;/** start y coordinate */private int starty;/** X The distance to be moved in the direction */private int distancex;/** The distance to move in the y direction */private int distancey;/** start time */private long starttime;/** move whether end */p Rivate Boolean isfinish;/** The coordinates of the current x-axis */private long currx;/** the coordinates of the current y-axis */private long curry;/** The default time interval */private int Durati            on = 500;public Myscroller (Context ctx) {}/** * starts moving * * @param startX * start x Coordinate * @param starty * The y-coordinate at the beginning * @param Distancex * The distance to be moved in the x direction * @param the distance to be moved in the Distancey * y direction */public void Startscroll (in T StartX, int starty, int distancex, int distancey) {this.startx = Startx;this.starty = Starty;this.distancex = Distancex; This.distancey = Distancey;this.starttime = Systemclock.uptimemillis (); this.isfinish = false;} /** * Determine current running status * * @return */public Boolean Computeoffset() {if (Isfinish) {return false;} Time taken to obtain long Passtime = Systemclock.uptimemillis ()-startTime; System.out.println ("Passtime::" + passtime);//If the time is still within the allowable range if (Passtime < duration) {Currx = StartX + Distancex * passt Ime/duration;curry = starty + Distancey * passtime/duration;} else {Currx = StartX + Distancex;curry = starty + Distancey;isfinish = true;} return true;} /** * Gets the value of the current x * * @return */public long Getcurrx () {return currx;} public void Setcurrx (long currx) {This.currx = Currx;} /** * Gets the value of the current y * * @return */public long Getcurry () {return currY;} public void Setcurry (long CurrY) {this.curry = CurrY;}}
Analysis, this process.

When we calculate the ID to switch to the next view, we can get the distance of the switch, the formula: the distance to move = The final position-the current position; after getting the distance, get the distance and the initial position, and tell the "engineer"-the tool Myscroller, This is the time to start calculating, and the initialization code is as follows:

Distance to move = final position-now position int Distancex = Currid * getwidth ()-GETSCROLLX ();//Set Run time Myscroller.startscroll (GETSCROLLX (), 0, Distancex, 0);//Refresh view invalidate ();
After initializing the calculation tool class, you need to refresh the current view, call the Invalidate () method, this method will pass through a series of chain reaction, actually refreshing the view is a very complex process, not explained here, until the trigger Computescroll () method, at this time, We need to rewrite the Computescroll () method of the parent class, and in this method, do some of our own operations:

/*** invalidate (); Causes the execution of this method */@Overridepublic void Computescroll () {if (Myscroller.computeoffset ()) {int newx = (int) Myscroller.getcurrx (); System.out.println ("Newx::" + newx); ScrollTo (newx, 0); invalidate ();}}

In this method, first call the tool class to calculate the displacement of the method Computeoffset () method, the method first to determine whether the view movement is complete, if the completion of the return false, if not completed, first get the motion time interval, If the current motion interval is within the total time interval of duration, then after the interval is calculated, the position of the view is actually moved to, the formula is: start position + total distance/Total time * This section moves the time interval , If the current motion time interval exceeds the total time interval, the last position is calculated directly, the formula: start position + moving distance . The distance of this displacement is obtained by GETCURRX, that is, the latest displacement distance, calling the Scrollto (Int,int) method, moving the view to the new position. Finally, recursively call invalidate () to refresh the current view, and then trigger the Computescroll () method to continue the above steps until the specified interval is exceeded, and the displacement process ends when the view is returned false.


In addition, in this example program I have customized a Myscroller tool class to calculate the displacement size, feel time-consuming and laborious, as a learning principle feasible, but in real development, can use Android to provide us with similar, extremely simple helper class, You can use this helper class to calculate displacements, and this class is

The following are the relevant methods of the Scroller class:

Mscroller.getcurrx ()Gets the position of the Mscroller current horizontal scroll
Mscroller.getcurry ()Gets the position of the Mscroller current vertical scroll
Mscroller.getfinalx ()Gets the horizontal position of the Mscroller final stop
mscroller.getfinaly ()Gets the vertical position of the Mscroller final stop
mscroller.setfinalx (int newx)Sets the horizontal position of the Mscroller final stop, without animation effect, jumps directly to the target position
mscroller.setfinaly (int newy)Set the vertical position of the Mscroller final stop, without animation effect, jump directly to the target position
mscroller.startscroll (int startX, int starty, int dx, int dy)Scroll, StartX, starty to start scrolling position, dx,dy for scrolling offset
mscroller.startscroll (int startX, int starty, int dx, int dy, int duration)Scroll, StartX, starty to start scrolling position, dx,dy for scrolling offset, duration for time to complete scrolling
Mscroller.computescrolloffset ()A return value of Boolean,true indicates that scrolling has not been completed and false indicates that scrolling is complete. This is a very important method, usually placed in View.computescroll (), to determine whether scrolling is over or not.

The specific use of scroller has been useful in my previous blog post, please go to the Android custom control-side-by-side menu to view the relevant source code.


Please download the source code here


Android Custom Viewpager (i)--custom scroller simulation animation process

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.