1. Overview
This is actually my first want to write the blog, probably because I met too many pits, at that time just entered a lot of demo found how also can not move, may be limited capacity, this time to do a concrete implementation and thorough encapsulation.
Last time I talked about the Android Unlimited advertising carousel-viewpager source Analysis, with the source analysis we have a general understanding of Viewpager, then to package into a custom view, it will be a lot simpler, with video explanation address: http://pan.baidu.com/s/1bpqqkGn
2. Effect Encapsulation
2.1 Custom Bannerviewpager extends Viewpager:
We want to use the adapter design pattern, then at this stage, the need for the method is based on the Pageradapter location to get the current view, so banneradapter only need a method that is getview (int position);
/** * Description: * AD Carousel Viewpager * Created by Zeng Hui on 2016/11/17. * qq:240336124 * Email: [Email protected] * Ve rsion:1.0 * * Public class bannerviewpager extends viewpager { PrivateContext Mcontext;PrivateBanneradapter Madapter; Public Bannerviewpager(Context context) { This(Context,NULL); } Public Bannerviewpager(context context, AttributeSet attrs) {Super(context, attrs); This. Mcontext = Context; } Public void Setadapter(Banneradapter adapter) { This. Madapter = Adapter; Setadapter (NewBannerpageradapter ()); }Private class bannerpageradapter extends pageradapter { @Override Public int GetCount() {//Returns a large value to ensure infinite carousel returnInteger.max_value; }@Override Public Boolean Isviewfromobject(View view, Object object) {//This is right, read the source should understand returnview = = object; }@Override PublicObjectInstantiateitem(ViewGroup container,Final intPosition) {View Bannerview = Madapter.getview (position); Container.addview (Bannerview);returnBannerview; }@Override Public void Destroyitem(ViewGroup container,intPosition, Object object) {//Destroy the callback method to remove the pageContainer.removeview ((View) object); } }}
So we just give him to set a banneradapter can achieve viewpager effect, can be manually switched, here first do not look at the effect.
2.2. Implement Automatic Carousel
The implementation of automatic rotation is relatively simple, the way to achieve a variety of timers can be timer, handler send messages, start thread line, here I use handler send a message method.
//2. Msg that sends a delay message Private Final intRoll_msg =0x0011;//2. Implement automatic carousel-handler send messages PrivateHandler Mrollhandler =NewHandler () {@Override Public void Handlemessage(Message msg) {//Switch to the next pageSetcurrentitem (Getcurrentitem () +1);//Cyclic executionStartroll (); } };/** * Automatic scrolling * * * Public void Startroll() {mrollhandler.removemessages (roll_msg);//Send delayed MessagesMrollhandler.sendemptymessagedelayed (roll_msg, mcutdowntime); }
Let's take a look at the effect, but found that GIF recording does not capture the effect of switching, because the automatic switching speed is too fast, here or not paste effect, below I need to change the speed of the switch.
2.4. Change the switching rate
If you have read the source code of the previous article, we will call Scroller's Mscroller.startscroll (SX, sy, DX, dy, duration) This method, If we need to change the rate can only change the duration to perform the switch page animation time, but we do not get this value, then we can only modify the Mscroller this property, but also found that he is private a bit big, but we can use the reflection set Mscroller;
//Custom inherited sub-scroller PrivateBannerscroller Mscroller; Public Bannerviewpager(context context, AttributeSet attrs) {Super(context, attrs); This. Mcontext = Context;Try{//3. Change the duration of the toggle page animation get Mscroller property by ReflectionField field = ViewPager.class.getDeclaredField ("Mscroller"); Field.setaccessible (true); Mscroller =NewBannerscroller (context);//Set Scroller to our custom scroller classField.set ( This, Mscroller); }Catch(Exception e) {E.printstacktrace (); } }/** * Set the duration of the toggle page animation **/ Public void setscrollerduration(intscrollerduration) {mscroller.setscrollduration (scrollerduration); }
Now the effect is almost, you can see the infinite Carousel, automatic rotation, and the speed of the page switching is also possible, then only need to deal with the point of indicator and text description:
2.5. Custom Bannerview Join point instructions and ad descriptions
Next we customize a bannerview that contains the current custom Bannerviewpager and points linearlayout as well as the ad description TextView.
/** * Description: * AD Carousel * Created by Zeng Hui on 2016/11/17. * qq:240336124 * Email: [Email protected] * version:1.0 * / Public class bannerview extends relativelayout implements Viewpager . Onpagechangelistener { @ViewById(R.ID.BANNER_DESC_TV)PrivateTextView MBANNERDESCTV;@ViewById(R.ID.DOTS_LL)PrivateLinearLayout Mdotcontainer;PrivateBanneradapter Madapter;PrivateDrawable mnormaldotdrawable, mfocusdotdrawable;PrivateContext Mcontext;Private intMcurrentposition =0;Private intMdotlocation =1;@ViewById(R.ID.BANNER_VP)PrivateBannerviewpager Mviewpager;//AD bit width-to-height ratio Private floatMwidthproportion, mheightproportion;Private intMcalculateheight =0; Public Bannerview(Context context) { This(Context,NULL); } Public Bannerview(context context, AttributeSet attrs) { This(Context, Attrs,0); } Public Bannerview(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); This. Mcontext = Context; Initattribute (ATTRS); Inflate (context, r.layout.ui_banner_layout, This); Viewutils.inject ( This); }Private void Initattribute(AttributeSet attrs) {TypedArray array = mcontext.obtainstyledattributes (Attrs, R.styleable.bannerview); Mdotlocation = Array.getint (r.styleable.bannerview_dotlocation, mdotlocation); mfocusdotdrawable = array.getdrawable (R.styleable.bannerview_dotindicatorfocus);if(Mfocusdotdrawable = =NULL) {mfocusdotdrawable =NewColordrawable (color.red); } mnormaldotdrawable = Array.getdrawable (r.styleable.bannerview_dotindicatornormal);if(Mnormaldotdrawable = =NULL) {mnormaldotdrawable =NewColordrawable (Color.White); } mwidthproportion = Array.getfloat (r.styleable.bannerview_widthproportion, mwidthproportion); Mheightproportion = Array.getfloat (r.styleable.bannerview_heightproportion, mheightproportion); Array.recycle (); } Public void Setonbanneritemclicklistener(Bannerviewpager.banneritemclicklistener Listener) {Mviewpager.setonbanneritemclicklistener (listener); }@Override protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec);if(Mwidthproportion! =0&& mheightproportion! =0&& Mcalculateheight = =0) {intwidth = Getmeasuredwidth ();if(Mheightproportion = =0|| Mwidthproportion = =0) {return; } Mcalculateheight = (int) (width * mheightproportion/mwidthproportion); Setmeasureddimension (width, mcalculateheight); Mviewpager.getlayoutparams (). height = mcalculateheight; } } Public void Setadapter(Banneradapter adapter) { This. Madapter = Adapter; Mviewpager.setadapter (adapter); Initdotindicator (Madapter.getcount ()); Mviewpager.addonpagechangelistener ( This); String Textdesc = Madapter.getbannerdesc (0);if(! Textutils.isempty (Textdesc)) {mbannerdesctv.settext (TEXTDESC); } }Private void Initdotindicator(intCount) {mdotcontainer.setgravity (getdotgravity ()); for(inti =0; I < count; i++) {Dotindicatorview Indicatorview =NewDotindicatorview (Mcontext); Linearlayout.layoutparams params =NewLinearlayout.layoutparams (dip2px (8), dip2px (8)); Params.leftmargin = Params.rightmargin = dip2px (2); Indicatorview.setlayoutparams (params);if(i = = mcurrentposition) {indicatorview.setdrawable (mfocusdotdrawable); }Else{indicatorview.setdrawable (mnormaldotdrawable); } mdotcontainer.addview (Indicatorview); } }Private int dip2px(intDIP) {return(int) typedvalue.applydimension (Typedvalue.complex_unit_dip, DIP, Getresources (). Getdisplaymetrics ()); } Public void Startroll() {mviewpager.startroll (); }@Override Public void onpagescrolled(intPositionfloatPositionoffset,intPositionoffsetpixels) {}@Override Public void onpageselected(intPosition) {Dotindicatorview Oldindicatorview = (dotindicatorview) mdotcontainer.getchildat (mcurrentposition); Oldindicatorview.setdrawable (mnormaldotdrawable); mcurrentposition = position% madapter.getcount (); Dotindicatorview Currentindicatorview = (dotindicatorview) mdotcontainer.getchildat (mCurrentPosition); Currentindicatorview.setdrawable (mfocusdotdrawable); Mbannerdesctv.settext (Madapter.getbannerdesc (mcurrentposition)); }@Override Public void onpagescrollstatechanged(intState) {} Public int getdotgravity() {Switch(mdotlocation) { Case-1:returnGravity.left; Case 0:returnGravity.center; Case 1:returnGravity.right; }returnGravity.left; }}
If you really do not understand, you can look at my recording frequency, you can also learn about the whole project of other things: Http://pan.baidu.com/s/1bpqqkGn.
Attached code address:
http://download.csdn.net/detail/z240336124/9683704
Android Unlimited AD carousel-Custom Bannerview