****************************************************************************
Time:2015-01-13
Sharing_li
Reprint Source: http://blog.csdn.net/sharing_li/article/details/42685321
****************************************************************************
When we use COCOS2DX's TableView and ScrollView, if we want to display a lot of content, we are not convenient to confirm where the current browsing content is located, and it is not convenient to quickly browse. At this point we need a scroll bar to help, but cocos2dx there is no control, so, here I give you a scroll bar control scrollbar, can be very convenient to use. Before you start, take a look:
After watching, let's confirm the functional requirements:
1, by sliding TableView or ScrollView, the right slider also follow the slide;
2, TableView or scrollview slip to the end, the right slider also slipped to the end;
3, when you click on the right slider slide, the left TableView or ScrollView also follow the slide;
4, slide to the end, TableView or ScrollView also slipped to the end;
5, when clicking on the right slider background, that is, the example yellow part, TableView or ScrollView and sliders are sliding with the person;
6, when the content of TableView or ScrollView increases dynamically, the size of the slider also changes dynamically;
7, control horizontal and vertical can be used, the example only shows the vertical effect, the same level;
The general function is so much, so let's see how the code is written, we define a class scrollbar:
ScrollBar.h header File
#ifndef _scroll__bar__h_#define _scroll__bar__h_#include "cocos2d.h" #include "cocos-ext.h" USING_NS_CC; Using_ns_cc_ext;enum Sclbardirection{dir_nodir = 0,dir_vertical,dir_horizental,};class scrollbar:public cocos2d:: Layer{public:scrollbar (); ~scrollbar ();/*** because the nine map can not be reduced to a smaller than the actual picture, so the actual size of the incoming picture is small enough, otherwise the size of the slider will be a problem */static ScrollBar * Create (Scale9sprite * bar_bg,scale9sprite * bar_slider,tableview * tableview,sclbardirection dir); Static ScrollBar * Create (const char * bar_bgfile,const char * bar_sliderfile,tableview * tableview,sclbardirection dir); bool Myinit ( Scale9sprite * Bar_bg,scale9sprite * bar_slider,tableview * tableview,sclbardirection dir);p rotected:virtual bool Ontouchbegan (touch* touch, event* pevent); virtual void ontouchmoved (Touch *ptouch, Event *pevent); virtual void ontouchended (Touch *ptouch, Event *pevent); virtual void update (float DT) override;/*** dynamically changes the size of the slider */void updateslider ();p Rivate:tableview * m_ptarget; Scale9sprite * M_PBG; Scale9sprite * M_pslider; Sclbardirection M_direction; Size m_precontentsize; Size M_viewsize;bool m_slidertouched; VEC2 M_firsttouch; VEC2 M_slidercurpos; VEC2 M_targetcurpos;}; #endif
Some comments are given in the code, and we use the nine figure scale9sprite to display the slider and slider background image, because the scale9sprite is fine when zooming, and does not cause the picture to deteriorate because of the stretch. It is worth noting that if the actual size of your picture is so large, then the scale9sprite can not be reduced to smaller than size, and the opposite will be magnified. So the incoming picture to be small enough, the following to see the specific implementation:
First initialize the data:
/*** initializes individual data */bool scrollbar::myinit (scale9sprite * bar_bg,scale9sprite * Bar_slider,tableview * TableView, Sclbardirection dir) {if (! Layer::init ()) {return false;} M_PBG = Bar_bg;m_pslider = Bar_slider;m_ptarget = Tableview;m_direction = Dir;m_precontentsize = m_pTarget-> GetContainer ()->getcontentsize (); m_viewsize = M_ptarget->getviewsize (); if (m_direction = = DIR_VERTICAL) {m_ Pbg->setcontentsize (Size (M_pbg->getcontentsize () width,m_viewsize.height)) M_pbg->setposition (VEC2 (m_ Pbg->getcontentsize (). width/2,0); M_pslider->setpositionx (M_pbg->getcontentsize (). WIDTH/2);} else if (m_direction = = dir_horizental) {m_pbg->setcontentsize (Size (M_viewsize.width,m_pbg->getcontentsize ()). height)); M_pbg->setposition (VEC2 (0,-m_pbg->getcontentsize () height/2)); M_pslider->setpositiony (-m_ Pbg->getcontentsize (). HEIGHT/2);} This->addchild (m_pbg,0); This->updateslider (); This->addchild (m_pslider,1); This->scheduleupdate (); Auto Listenert = EventListenerTouchonebyone::create (); Listenert->ontouchbegan = Cc_callback_2 (scrollbar::ontouchbegan,this);listenerT-> ontouchmoved = Cc_callback_2 (scrollbar::ontouchmoved,this); listenert->ontouchended = CC_CALLBACK_2 (ScrollBar::o Ntouchended,this); Listenert->setswallowtouches (false);D irector::getinstance ()->geteventdispatcher () Addeventlistenerwithscenegraphpriority (listenert,this); return true;}
Let's take a look at how the Updateslider function changes the size of slider sliders:
void Scrollbar::updateslider () {Float ratio = 0.0;if (m_direction = = dir_vertical) {ratio = M_viewsize.height/m_preconten Tsize.height; M_pslider->setcontentsize (Size (M_pslider->getcontentsize (). Width,m_viewsize.height * ratio));} else if (m_direction = = Dir_horizental) {ratio = M_viewsize.width/m_precontentsize.width;m_pslider->setcontentsize (Size (M_viewsize.width * ratio,m_pslider->getcontentsize (). height));} If the size of the content you want to display is smaller than the view size, hide the slider sliderthis->setvisible (!) ( Ratio >= 1));}
I got a timer to listen to the TableView or ScrollView slide, which is the offset:
void Scrollbar::update (float dt) {//To determine whether the current content has increased or decreased, because the contents of the increase and decrease will affect contensize, thus modifying the size of the slider auto curcontentsize = m_ptarget- >getcontainer ()->getcontentsize (); if (!) ( FABSF (curcontentsize.height-m_precontentsize.height) <= 0.00001) | | ! (FABSF (curcontentsize.width-m_precontentsize.width) <= 0.00001)) {m_precontentsize = Curcontentsize;this->updateslider ();} Set the position of the slider if (m_direction = = dir_vertical) {//adjust the position of the slider auto Curoffset = M_ptarget->getcontentoffset () + (m_ precontentsize-m_viewsize)/2;auto Slideroffset = CUROFFSET.Y/(m_viewsize.height-curcontentsize.height) * (m_viewSi Ze.height-m_pslider->getcontentsize (). height);//Determine if the slider is sliding out of bounds if (FABSF (Slideroffset) > (m_viewsize.height-m_ Pslider->getcontentsize (). Height)/2) {return;} M_pslider->setpositiony (Slideroffset);} else if (m_direction = = dir_horizental) {Auto Curoffset = M_ptarget->getcontentoffset ()-(M_precontentsize-m_viewsiz e)/2;auto Slideroffset =-curoffset.x/(M_viewsize.width-curcontentsiZe.width) * (M_viewsize.width-m_pslider->getcontentsize (). width), if (FABSF (Slideroffset) > (M_viewsize.width- M_pslider->getcontentsize (). width)/2) {return;} M_pslider->setpositionx (Slideroffset);}}
Note that the sliding size of the TableView or ScrollView is not the same as the sliding size of the slider, so the two should be proportional to the slide if they want to be synchronized.
Then take a look at the slider slide and the slider background click on this piece of implementation:
First Look at Ontouchbegan:
BOOL Scrollbar::ontouchbegan (touch* Touch, event* pevent) {m_slidercurpos = M_pslider->getposition (); m_ Targetcurpos = M_ptarget->getcontentoffset (); Auto TouchPoint = Touch->getlocation (); M_firsttouch = touchPoint;/ /Convert the touch point to the coordinates under the current sub-layer TouchPoint = This->converttonodespace (touchPoint);//respond only to touch if the slider background is clicked (!m_pbg->getboundingbox (). Containspoint (TouchPoint)) {return false;} If you click the slider first, set the flag if (M_pslider->getboundingbox (). Containspoint (TouchPoint)) {m_slidertouched = true;} else//If you do not click the slider, click on the slider background {if (m_direction = = dir_vertical) {//adjust the position of the slider slider by adjusting the m_ptarget offset, as the update function will always listen m_ Ptarget Offset Auto offset = touchpoint.y-m_slidercurpos.y;if (touchpoint.y <= 0) {offset + = M_pslider->getcontentsize (). Height/2;} Else{offset-= M_pslider->getcontentsize (). HEIGHT/2;} Auto Newoff = M_targetcurpos.y + offset/(M_pslider->getcontentsize (). Height-m_viewsize.height) * (m_precontentsize . height-m_viewsize.height); M_ptarget->setcontentoffset (VEC2 (0,newoff));} else if (m_direction = = dir_horizental) {Auto offset = touchpoint.x-m_slidercurpos.x;if (touchpoint.x <= 0) {offset + = M_pslider->g Etcontentsize (). Width/2;} Else{offset-= M_pslider->getcontentsize (). Width/2;} Auto Newoff = m_targetcurpos.x + offset/(M_viewsize.width-m_pslider->getcontentsize (). Width) * (M_PRECONTENTSIZE.W Idth-m_viewsize.width); M_ptarget->setcontentoffset (VEC2 (newoff,0));}} return true;}
Here's a little bit of attention, I don't need to modify the position of the slider in the touch function, because we modify the offset of the ScrollView or TableView, Thus indirectly changing the position of the slider, so we just need to properly set the position of ScrollView or tableview, the update function will help us to solve the position of the slider.
Take a look at ontouchmoved:
void Scrollbar::ontouchmoved (Touch *ptouch, Event *pevent) {//Response only if the slider is clicked (m_slidertouched) {Auto Offpos = ptouch-> GetLocation ()-m_firsttouch;if (m_direction = = dir_vertical) {//adjust the position of the slider slider by adjusting the m_ptarget offset, because the update function will always listen m_ Ptarget Offset Auto Newoff = m_slidercurpos.y + offpos.y;//Determine if the slider is slipping out of bounds if (FABSF (Newoff) > (m_viewsize.height-m_pslider-& Gt;getcontentsize (). Height)/2) {(Newoff < 0?) (Newoff = (M_pslider->getcontentsize (). Height-m_viewsize.height)/2): (Newoff = (m_viewsize.height-m_pslider-> Getcontentsize (). Height)/2));} Newoff-= M_slidercurpos.y;m_ptarget->setcontentoffset (VEC2 (0,m_targetcurpos.y + newoff/(m_pSlider-> Getcontentsize (). Height-m_viewsize.height) * (M_precontentsize.height-m_viewsize.height));} else if (m_direction = = dir_horizental) {Auto Newoff = m_slidercurpos.x + offpos.x;if (FABSF (Newoff) > (m_viewsize.width -M_pslider->getcontentsize (). width)/2) {(Newoff < 0?) (Newoff = (M_pslider->getcontentsize (). Width-m_vieWsize.width)/2): (Newoff = (M_viewsize.width-m_pslider->getcontentsize (). width)/2));} Newoff-= M_slidercurpos.x;m_ptarget->setcontentoffset (VEC2 (m_targetcurpos.x + newoff/(m_viewsize.width-m_ Pslider->getcontentsize (). Width) * (m_precontentsize.width-m_viewsize.width), 0);}}}
Finally, let's look at ontouchended:
void scrollbar::ontouchended (Touch *ptouch, Event *pevent) {m_slidertouched = false;}
Very simple, just one sentence, to restore the slide slider of the touch state on it. Here, the custom control scrollbar has been implemented. So we're looking at how to use scrollbar in code. Also very simple, see the following example:
M_tableview = Tableview::create (this,viewsize); m_tableview->ignoreanchorpointforposition (false); m_tableView- >setanchorpoint (VEC2 (0.5,0.5)); M_tableview->setposition (VEC2 (VIEWSIZE.WIDTH/2,VIEWSIZE.HEIGHT/2)); m_ Tableview->setdirection (ScrollView::D irection::vertical); M_tableview->setdelegate (this);m_tableview-> Setverticalfillorder (Tableview::verticalfillorder::top_down); M_tableview->reloaddata ();p View->addchild (M _tableview); Auto SCROLLBAR_VR = Scrollbar::create ("Scrollbar/vr_slider_bg.png", "Scrollbar/vr_slider.png", m_ tableview,dir_vertical); Scrollbar_vr->setposition (VEC2 (VIEWSIZE.WIDTH,VIEWSIZE.HEIGHT/2));p view-> AddChild (scrollbar_vr,2);
Once you've created your tablewview or scrollview, simply create a scrollbar, set the location, and add it to the parent node in a total of three steps to make it easy.
This time the content is finished, there are doubts can leave a message.
Demo Resources Download out: http://download.csdn.net/detail/sharing_li/8359125
Design of COCOS2DX custom control scrollbar