GitHub Address: Https://github.com/zerohuan/SlideLayout/tree/master
Actual:
The custom control inherits Framelayout, which contains a viewpager and a horizontally arranged linearlayout. The latter is used to contain a set of points that show the carousel location, and the advantage of using Viewpager is the flexibility to define the content of the item, not just the picture. </p><p></p><p> for ease of use, define the required operating parameters by customizing the properties: </p><p><pre name= "code" class= " HTML "><declare-styleable name=" Slidelayout "> <attr name=" Viewpagerid "format=" Reference "/> <attr name= "Dotsid" format= "reference"/> <attr name= "AutoPlay" format= "boolean"/> < attr name= "Slide_interval" format= "integer"/> <attr name= "Dotradius" format= "Dimension"/> < attr name= "Ondotcolor" format= "color"/> <attr name= "offdotcolor" format= "color"/> <attr name= " Strokecolor "format=" color "/> </declare-styleable>
The corresponding data members are as follows:
Carousel Container Viewpager private Viewpager Viewpager; Dot set of marked position private linearlayout dots; The resource ID of the Viewpager private int viewpagerid; The resource ID of the linearlayout that contains the point is private int dotsid; The PX-DP ratio of the mobile phone is private float scale; Viewpager Adapter private Pageradapter adapter; Whether to play the private Boolean isautoplay automatically; The interval of the play private int interval; Current page position private int currentitem; Dot radius private float Dotradius; Whether the private Boolean isrunning is running on the carousel ; On the current page, the color of the DOT flag is private int ondotcolor; is not on the current page, the color of the DOT flag is private int offdotcolor; Dot border color private int strokecolor; Private final static int scroll_what = 0x7549;
When used, it is defined by an XML file:
<com.luckymore.ydd.app.view.selfview.slidelayout xmlns:attrs= "Http://schemas.android.com/apk/res-auto" Android:id= "@+id/news_slide_bar" android:layout_width= "Match_parent" android:l ayout_height= "Match_parent" swipe:dotsid= "@+id/test_1" attrs:viewpagerid= "@+id/test_2" Attrs:autoplay= "true" attrs:dotradius= "3DP" attrs:slide_interval= "4000" Attrs:offdotcolor= "@color/alpha_black" attrs:ondotcolor= "@color/alpha_white" Attrs:stro Kecolor= "#77626262" > <android.support.v4.view.viewpager android:id= "@+id/test_2" Android:layout_width= "Match_parent" android:layout_height= "Match_parent"/> <linearlayout android:id= "@+id/test_1" android:layout_width= "Wrap_content" Android:layout_height= "20DP "android:orientation=" horizontal "android:layout_gravity=" Bottom|center_horizont Al "android:gravity=" center "android:paddingleft=" 8DP "Android:pa ddingright= "8DP"/> </com.luckymore.ydd.app.view.selfView.SlideLayout>
To get a custom parameter value:
/** * Gets a custom parameter, called in the constructor * @param context * @param attrs */private void init (context context, Attributese T...attrs) {if (Attrs.length > 0) {TypedArray TypedArray = context.obtainstyledattributes (Attrs[0], R.styleable.slidelayout); Viewpagerid = Typedarray.getresourceid (R.styleable.slidelayout_viewpagerid,-1); Dotsid = Typedarray.getresourceid (R.styleable.slidelayout_dotsid,-1); Scale = Getresources (). Getdisplaymetrics (). density; Isautoplay = Typedarray.getboolean (R.styleable.slidelayout_autoplay, false); Interval = Typedarray.getinteger (r.styleable.slidelayout_slide_interval, 4000); Dotradius = Typedarray.getdimension (r.styleable.slidelayout_dotradius, 2f * scale); Ondotcolor = Typedarray.getcolor (R.styleable.slidelayout_ondotcolor, 0X77FFFFFF); Offdotcolor = Typedarray.getcolor (R.styleable.slidelayout_offdotcolor, 0x77000000); Strokecolor = TypedaRray.getcolor (R.styleable.slidelayout_strokecolor, 0x77626262); } }
Viewpager ID and LinearLayout ID are passed in by custom attributes, injected into Slidelayout,implemented in Onfinishinflate:
@Override protected void Onfinishinflate () {super.onfinishinflate (); if (Viewpagerid! =-1 && dotsid! =-1) {Viewpager = (Viewpager) Findviewbyid (Viewpagerid); Dots = (linearlayout) Findviewbyid (DOTSID); Viewpager.setonpagechangelistener (New Viewpager.onpagechangelistener () {@Override public vo ID onpagescrolled (int i, float v, int i2) {} @Override public void Onpagesel ected (int i) {currentitem = i; for (int j = 0; J < Viewpager.getadapter (). GetCount (); j + +) {Dotview dot = (Dotview) Dots.getchil DAt (j); if (j = = i) Dot.seton (true); else Dot.seton (false); Dot.invalidate (); }} @Override public void Onpagescrollstatechanged (int i) {switch (i) {case 1://gesture swipe, idle Isautoplay = false; Break Case 2://Interface Switch isautoplay = true; Break Case 0://sliding end, that is, the switch is complete or loaded//is currently the last one, at this time from right to left, then switch to the first if (Viewpager. Getcurrentitem () = = Viewpager.getadapter (). GetCount ()-1 &&!isautoplay) {Viewpag Er.setcurrentitem (0); }//is currently the first one, which is now sliding from left to right, then switches to the last else if (viewpager.getcurrentitem () = = 0 &&!isautoplay) {Viewpager.setcurrentitem (Viewpager.getadapter (). GetCount ()-1) ; } break; } } }); } }
Next, the "point" in LinearLayout is populated, and the inner class Dotview is defined first:
/** * Dot ui, square view, contains a circular dot */public class Dotview extends View {private Paint mpaint = new Paint (); The two states, whether the current page private Boolean isOn; Square side length private int msize; Public Dotview (Context context) {super (context); } public Dotview (context context, AttributeSet Attrs) {Super (context, attrs); } public Dotview (context context, AttributeSet attrs, int defstyleattr) {Super (context, Attrs, Defstyle ATTR); }/** * OnDraw first executed * @param widthmeasurespec * @param heightmeasurespec */@ Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {msize = (int) Math.ceil ( Dotradius) * 3; Setmeasureddimension (Measurewidth (Widthmeasurespec), Measureheight (Heightmeasurespec)); } private int Measurewidth (int measurespec) {int result = 0; int Specmode = Measurespec.getmode (MEASURESPEC); int specsize = measurespec.getsize (Measurespec); if (Specmode = = measurespec.exactly) {//We were told how big to be result = specsize; } else {//Measure the text result = Msize + getpaddingleft () + getpaddingright (); if (Specmode = = Measurespec.at_most) {//Respect At_most value if that's what's call ed for by//Measurespec result = Math.min (result, specsize);//60,480 }} return result; } private int Measureheight (int measurespec) {int result = 0; int specmode = Measurespec.getmode (Measurespec); int specsize = measurespec.getsize (Measurespec); if (Specmode = = measurespec.exactly) {//We were told how big to be result = specsize; } else { Measure the text (beware:ascent is a negative number) result = Msize + getpaddingtop () + Getpad Dingbottom (); if (Specmode = = Measurespec.at_most) {//Respect At_most value if that's what's called for by Measurespec result = Math.min (result, specsize); }} return result; }//Draw point @Override protected void OnDraw (canvas canvas) {super.ondraw (canvas); Mpaint.setantialias (TRUE); if (IsOn ()) {Mpaint.setcolor (ondotcolor); } else {mpaint.setcolor (offdotcolor); } mpaint.setstyle (Paint.Style.FILL); Canvas.drawcircle (Dotradius, Dotradius, Dotradius, Mpaint); Mpaint.setstyle (Paint.Style.STROKE); Mpaint.setstrokewidth (0.7f * scale); Mpaint.setcolor (Strokecolor); Canvas.drawcircle (dOtradius, Dotradius, Dotradius, Mpaint); } public boolean isOn () {return isOn; The public void SetOn (Boolean isOn) {This.ison = IsOn; } }
Dotview contains the current page two states, and the fill color and border color are obtained from the custom properties.
In the Slidelayout member function resetdots fills the Dotview:
/** * Regenerate the point set UI */public void resetdots () {int dotcount = Viewpager.getadapter (). GetCount (); int olddotcount = Dots.getchildcount (); for (int i = 0; i < dotcount; i + +) { Dotview dot; & nbsp if (i >= olddotcount) { dot = new Dotview (GetContext ()); &N Bsp Dots.addview (dot); } else {  ; dot = (Dotview) dots.getchildat (i); &NBS P } if (i = = Viewpager.getcurrentitem ()) { Dot.seton (true); } else { Dot.seton (false); } }}
When the number of Dotview in the LinearLayout point set is less than the pager quantity in Viewpager, the new Dotview is populated to linearlayout;
The main calls to use Slidelayout in the UI thread are the following two methods:
/** * called in the UI thread, injected Viewpager adapter * @param adapter * /public void Setviewpageradapter (Pageradapter Adapter) { This.adapter = adapter; Viewpager.setadapter (adapter); UpdateUI (); } /** * called in UI thread, after modifying data in adapter, update UI * /public synchronized void UpdateUI () { Adapter.notifydatasetchanged (); Resetdots (); if (isautoplay) startautoscroll (); }
Finally, the implementation of timed rotation, through the handler&message Message Queuing mechanism to implement the carousel, the use of sendemptymessagedelayed to achieve the Carousel interval:
Private Handler Handler = new Handler () {@Override public void Handlemessage (Message msg) {Super . Handlemessage (msg); Switch (msg.what) {case scroll_what:synchronized (slidelayout.this) { Viewpager.setcurrentitem (CurrentItem); Sendscrollmessage (interval); } break; } } }; /** * Start Automatic carousel */public void Startautoscroll () {if (!isrunning) {isrunning = true; Sendscrollmessage (interval); }}/** * Scroll to the next page * @param delaytimeinmills */private synchronized void Sendscrollmessage (Long Delayt Imeinmills) {/** Remove messages before, keeps one message is running at most **/handler.removemessages (SC Roll_what); CurrentItem = (currentitem + 1)% adapter.getcount (); This method realizes the timed Carousel handler.sendemptymessagedelayed (Scroll_what, Delaytimeinmills); }
Finally, invoking a code in the UI thread allows you to use the Carousel control:
Newsbar.setviewpageradapter (New Newsbaradapter (Ret.getnews (), getmactivity ()));
android--Carousel control with position hints