Android Custom Control---navigation bar slidetab (Fragment+viewpager)

Source: Internet
Author: User

First, preface

I haven't updated my blog for a long time. Share a custom control with a navigation bar today. The demo about this control is believed to be on the internet already rotten Street, a search a lot of.
I am now only focusing on sharing some of the points that I think are more difficult to understand. There are about three difficulties in the entire control
1, the cursor drawing.
2, Viewpager listener understanding.
3, the movement of the cursor.
This article will focus on these three aspects of the focus of analysis.

The final result of the demo first

II. Demo chart and Knowledge Point

Sample module, with four Java files and two XML files

Summarize the main points of knowledge for this control
1, ViewGroup drawing process.
2, the use of Viewpager.
3, the use of Onpagechangelistener interface.
4, the use of Scrollto method.

Need complete code, please look at the bottom link, thank you! (^_^). Below I speak directly the core code.

Third, Slidetab navigation bar control

(1) After Slidetab inherits the Horizontalscrollview control, we need to rewrite the OnDraw method. Next you need to look at a diagram to understand the internal composition of the Slidetab control

The entire Slidetab control is made up of these three types of controls. Assume that the Slidetab control has been initialized to completion. The first time the OnDraw method is called by the system.

/** * @param canvas * *    @Override    protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas);//Gets the horizontal values of the left and right sides of the current tabView Currenttabview = Horizontalcontainer.getchildat (currentposition);floatCURRENTTABLEFTX = Currenttabview.getleft ();floatCURRENTTABRIGHTX = Currenttabview.getright ();intChildCount = Horizontalcontainer.getchildcount ();//viewpager calls the OnDraw method repeatedly during the sliding process. The contents of the IF statement below are used to calculate the start and end coordinates of the cursor        if(Currentpositionoffset >0F && currentposition < ChildCount-1) {//Get the horizontal values on the left and right sides of the next tabView Nexttab = Horizontalcontainer.getchildat (currentposition +1);floatNEXTTABLEFTX = Nexttab.getleft ();floatNEXTTABRIGHTX = Nexttab.getright ();//Calculate starting pointCURRENTTABLEFTX = (Currentpositionoffset * NEXTTABLEFTX + (1F-currentpositionoffset) * CURRENTTABLEFTX);//Calculate end pointCURRENTTABRIGHTX = (Currentpositionoffset * nexttabrightx + (1F-currentpositionoffset) * currenttabrightx); }//Draw underline//Drawunderline (canvas, horizontalcontainer);        //Draw indicatorDrawindicator (Canvas, CURRENTTABLEFTX, CURRENTTABRIGHTX); }

The initial value of the currentposition variable is 0.
Line 8th Code View Currenttabview = Horizontalcontainer.getchildat (currentposition); Gets the view (actually TextView) of the first view inside the LinearLayout container.

9th, the top-left and upper-right coordinates of the view are given in 10 rows respectively.

The 11th row gets the total number of TextView controls in the LinearLayout container.

The Judgment statement for Line 13th. Currentpositionoffset This is a record of the current page in the sliding process of the offset (if you do not understand first put down, and then say) the initial value is 0, it is clear that currentpositionoffset is not much more than the 0F,IF statement is not established, Skip (The contents of the If statement are analyzed later). Keep going.

Go to the bottom 28 line to execute the Drawindicator method and start drawing the cursor.

(2) Now to solve the first difficulty of this control, the cursor is drawn.
This cursor is actually a line. To draw a first must be determined two points of the coordinate values (middle school knowledge, two points to determine a straight line).

/** * Draw cursor * * @param  Canvas Slidetab control's artboard * @param  CURRENTLEFTX title control The left coordinate of * @param  CURRENTRIGHTX the right coordinate of the caption control */  void  drawindicator  (canvas canvas , float  currentleftx, float  currentrightx) {float  indicatormiddle = (indicatorpaint.getstrokewidth ()/        2 );        float  indicatory = getheight ()-indicatormiddle;    Canvas.drawline (CURRENTLEFTX, Indicatory, CURRENTRIGHTX, Indicatory, Indicatorpaint); }

To better understand these pieces of code, still draw a picture. The black box is the LinearLayout container, and the green box is a cursor.

The value of the green box height is indicatorpaint.getstrokewidth (). The next job is to calculate the orange dots on the left and right sides.

The red horizontal line represents the CURRENTLEFTX variable.
The blue horizontal line represents the CURRENTRIGHTX variable.
The red vertical bar represents the Indicatormiddle variable.
The pink vertical bar represents the indicatory variable.

The calculation method of the 9th and 10 lines is obtained
Left orange coordinate point (currentleftx,indicatory).
Right orange coordinate point (currentrightx,indicatory).

In line 11th, call the Canvas.drawline method, which is a way to draw a line, to draw a cursor. The final parameter of this method Indicatorpaint is a brush that describes the state of the line, such as color, width, whether the end of the line is rounded, and so on. )

The above content is the process of cursor drawing.

(3) How do I make the navigation bar control slide with the Viewpager after drawing the cursor? Now we need to write a Setviewpager method that associates (Fragment+viewpager) with the Slidetab control. This method is provided to the user (using your control's program ape) call. All they need is a Viewpager instance and an array of header names to complete the call to this control.

/** * @param viewpager user passed in Viewpager * @param titlestring title name */     Public void Setviewpager(Viewpager Viewpager, string[] titlestring) { This. Viewpager = Viewpager; AddTab (titlestring);//Set Viewpager listener eventsViewpager.addonpagechangelistener (NewSlidetabpageviewlistener ()); }/** * Add Tab * * @param titlestring Header Array */    Private void AddTab(string[] titlestring) {//Clear All controlsHorizontalcontainer.removeallviews (); for(inti =0; I < Viewpager.getadapter (). GetCount (); i++) {//Create a vertical container to wrap the textview belowTabverticalcontainer =NewLinearLayout (context);            Tabverticalcontainer.setorientation (linearlayout.vertical); Tabverticalcontainer.sethorizontalgravity (gravity.center_horizontal);//Set Click eventsTabverticalcontainer.setonclicklistener (NewViewpagerclicklistener (i)); Tabverticalcontainer.setverticalgravity (gravity.center_vertical);//Put the vertical linearlayout container into the horizontal linearlayout containerHorizontalcontainer.addview (Tabverticalcontainer, Isextendtab? expandedtablayoutparams:defaulttablay Outparams);if(Titlestring! =NULL) {//Create titleTextView textviews =NewTextView (context);                Textviews.settext (Titlestring[i]); Textviews.settextsize ( -); Textviews.settextcolor (Color.parsecolor ("#000000")); Textviews.setsingleline (true);            Tabverticalcontainer.addview (Textviews, textviewlayoutparams); }        }    }

Line 8th is a custom method. Set the title navigation bar based on the total number of pages in Viewpager. Logic is simpler than simple heap code, let's skip it.
We focus on the 10th line of code. Viewpager registers an instance of a listener event. This instance has three callback methods to monitor the user's swipe of the screen. See below for details (the cursor slide of the Slidetab control is very much related to this listener event.) )

(4) Slidetabpageviewlistener is the inner class of the Slidetab control, implements the Viewpager.onpagechangelistener interface, and this interface must implement 3 methods.
Now to solve the 2nd difficulty. is the Viewpager listener event.
public void onpagescrolled (int position, float positionoffset,int positionoffsetpixels)
This method is called when you swipe the page, and this method is called back until the slide stops.
Position represents the subscript for the current page. For example, if you have three tabs and now swipe from the first page to the second page, the subscript for this position is 0 (subscript starts from 0), and the subscript becomes 1 when you swipe to the second page position.
Positionoffset represents the percentage of the current page offset. We'll use this parameter later.
Positionoffsetpixels represents the current page offset pixel, which is not normally used.

public void onpagescrollstatechanged (int.)
This method is called when the state of the Viewpager page is changed. How do you understand this sentence?
1, if you touch the screen from the first page to slide to the second page this process, will be called back to this method (if your finger has been in the sliding state of this method will always be invoked), the value of state passed over is 1 means that is sliding.
2, after the sliding end, will again callback this method, passing the value of the state is 2 means that the sliding end.
3, after the end of the slide, if there is no other sliding operation, will again callback this method, passed the value of State is 0, indicating that viewpager processing idle status.

public void onpageselected (int position)
This method is called from the current page to another page, and the position is the subscript for the new page. Note that this method will not be called if you swipe back from the current page (and do not let go) while sliding down the page.

The above details about the Onpagechangelistener interface of Viewpager, with these bases, is a good way to explain the slidetabpageviewlistener inner class.

(5) Slidetabpageviewlistener inner class

 /** * Viewpager scrolling monitoring Events */     Public  class Slidetabpageviewlistener implements Viewpager. Onpagechangelistener {        @Override         Public void onpagescrolled(intPositionfloatPositionoffset,intPositionoffsetpixels) {currentposition = position;            Currentpositionoffset = Positionoffset; Scrolltocurrentposition (Position, (int) (Positionoffset * (Horizontalcontainer). Getchildat (position). GetWidth ()));//Redraw the OnDraw methodInvalidate (); }@Override         Public void onpagescrollstatechanged(intState) {}@Override         Public void onpageselected(intPosition) {}}

Finally, let's solve the last puzzle of this control and how to control the movement of the cursor. This is one of the hardest parts of my feeling to be clear.
Let's say we're touching the screen from the first page to the second page, in the process. The Onpagescrolled method above will always be called.

8th, the code for Line 9 is to update the current page subscript (currentposition) and the offset value of the page (Currentpositionoffset). These two variables have already been seen in the OnDraw method above.
Line 10th calls the Scrolltocurrentposition method (this method is important). Passes the current page subscript (value 0) and the offset value of the current view (TextView) past. The specific code is as follows.

/***** * * * @param position * @param offset */     Public void scrolltocurrentposition(intPositionintOffset) {intCurrentoffsetx = Horizontalcontainer.getchildat (position). GetLeft () + offset;intSTARTSCROLLX = Currentoffsetx;if(Position >0|| Offset >0) {//remainoffset indicates the remaining offsetSTARTSCROLLX = Currentoffsetx-remainoffset; }//If the displacement is changed, slide        if(Startscrollx! = lastscrollx) {//Update the distance of last slideLASTSCROLLX = STARTSCROLLX;//horizontalcontainer control starts slidingScrollTo (STARTSCROLLX,0); }    }

The statement on line 11th is set. Calculated to get STARTSCROLLX this is the actual sliding offset value of the Horizontalcontainer container.
Line 17th LASTSCROLLX The default initial value is 0, so the IF statement is also true.
Finally, start sliding the Horizontalcontainer container on line 21. (Note that if the value of STARTSCROLLX is greater than 0, slide to the left and less than 0 to the right.) )

Immediately after calling the invalidate () method, its internal code will back up what we just said about the OnDraw method. In the OnDraw method, the preceding code was executed and then to the IF statement, which was not explained just now, because it is in a sliding state at this time. The values of Currentpositionoffset and currentposition must be set.

(6) I'll post the code for the IF statement in the OnDraw method.

if(Currentpositionoffset >0f&& CurrentPosition < ChildCount-1) {//Get the horizontal values on the left and right sides of the next tabView Nexttab = Horizontalcontainer.getchildat (currentposition +1);floatNEXTTABLEFTX = Nexttab.getleft ();floatNEXTTABRIGHTX = Nexttab.getright ();//Calculate starting pointCURRENTTABLEFTX = (Currentpositionoffset * NEXTTABLEFTX + (1f-currentpositionoffset) * CURRENTTABLEFTX);//Calculate end pointCURRENTTABRIGHTX = (Currentpositionoffset * nexttabrightx + (1f-currentpositionoffset) * currenttabrightx); }

In line 3rd, since the slide is not finished, the value of currentposition at this point is still 0, and because currentposition + 1, Nexttab gets the value of the second TextView.
4th, line 5 Gets the coordinates of the Nexttab control (which is actually textview) on both sides.

7th, 10 lines calculate the starting point and end point of the target in the sliding process, that is, the coordinates of the red dots on the left and right sides.

After the calculation is complete. Finally, the Drawindicator method is called again to redraw the cursor.
So far the flow of Slidetab controls and Viewpager has gone. Thank you (^_^) Y

Iv. End of

Given the length of the relationship, I will no longer demonstrate the use of the control. You can download the demo below to see the source code. The Slidetabdemonstration class in the demo is the entrance.
This demo has bugs that are unavoidable. Limited to learning. I hope I can help you.

Demo Source please poke here (Android Studio compiler)

Android Custom Control---navigation bar slidetab (Fragment+viewpager)

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.