Cocos2d-x 3.2编写常用UI组件 《Cocos2d-x 3.2编写常用UI组件 带滚动的表格GridView

按照惯例先发上效果图:

20150129192649172.gif

正文:

一说起滚动效果大家可能会联想到Cocos2d-x给我们提供的ScrollView。我一开始也是打算用ScrollView来实现的,但是用着用着发现出现了各种莫名其妙的错误,所以只好自己重新写一个Node,通过onTouchBegan和onTouhMoved两个事件回调来实现滚动的效果。


GridView使用说明:

1.利用GridView::create(int row,int column)来创建一个GridView,row和column分别指定行数和列数。注意这里的行数是指可见的行数

2.通过GridView::addItem(Node* node)来向GridView里面添加元素


GridView实现思路:

1.创建的时候指定行数和列数

2.GridView里面新建一个Node(visibleNode)用于保存所有的item(以后实现滚动的时候方便点)

3.通过addItem进GridView时,计算出item的位置(x,y)

4.接受触摸事件

5.计算触摸的偏移量,visibleNode移动相应的距离

6.一头一尾的触摸要稍作判断(即不能上方出现空白或全空白)

7.添加遮罩层


核心代码解析:

1、添加Item

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void  GridView::addItem(Node* item){  
     if (getItemSize() == 0){<span style= "white-space:pre" >     </span> //如果是第一个Item(则以这个item为标准)  
         m_visible_node = Node::create();<span style= "white-space:pre" >    </span> //visibleNode用于保存所有的item  
         m_visible_node->setAnchorPoint(Point(0,0));  
         m_visible_node_posy_max = 0;<span style= "white-space:pre" >    </span> //m_visible_posy_max表示现在最大能移上去多少(对应于尾的判断)  
   
         m_item_width = item->getContentSize().width;<span style= "white-space:pre" > </span> //利用第一个Item来确定标准  
         m_item_height = item->getContentSize().height;  
         this ->setContentSize(  
             Size(m_item_width*m_column_num,m_item_height*m_row_num)  
             );  
         m_visible_node->setContentSize(  
             Size(m_item_width*m_column_num,m_item_height*m_row_num)  
             );  
         ClippingNode* cliper = ClippingNode::create();<span style= "white-space:pre" >  </span> //遮罩层  
         DrawNode* drawNode = DrawNode::create();  
         Point points[] = {Point(getPosition()),  
                         Point(getPositionX(),getPositionY()+m_row_num*m_item_height),  
                         Point(getPositionX()+m_column_num*m_item_width,getPositionY()+m_row_num*m_item_height),  
                         Point(getPositionX()+m_column_num*m_item_width,getPositionY())};  
           
         drawNode->drawPolygon(points,4,Color4F(0,0,0,1),0,Color4F(0,0,0,0));  
   
         LayerColor* stencil = LayerColor::create(Color4B(0x00, 0x00, 0x00, 0xC0), this ->getContentSize().width, this ->getContentSize().height);  
         stencil->setAnchorPoint(Point(0,0));  
           
         cliper->setStencil(stencil);  
         cliper->addChild(m_visible_node);  
         this ->addChild(cliper);  
           
         scrollbar = ScrollBar::create(m_row_num*m_item_height);<span style= "white-space:pre" > </span> //滚动条(下面会讲到可以先跳过)  
         scrollbar->setPosition(m_item_width*m_column_num,0);  
         this ->addChild(scrollbar);  
   
     }  
     item->setAnchorPoint(Point(0,1));  
   
     int  index = getItemSize() + 1;  
     float  x = (index-1)%m_column_num * m_item_width;<span style= "white-space:pre" >    </span> //计算出item的x,y  
     float  y = m_item_height*m_row_num - ((index-1)/m_column_num * m_item_height);  
     item->setPosition(Point(x,y));  
     int  cur_max_row = (index-1)/m_column_num+1;  
     if (cur_max_row > m_row_num){<span style= "white-space:pre" >         </span> //如果当前最大行数超过可见行  
         m_visible_node_posy_max = (cur_max_row-m_row_num)*m_item_height;<span style= "white-space:pre" >    </span> //设置最大能移上去多少  
         scrollbar->setButtonSize(m_row_num*1.0/cur_max_row);<span style= "white-space:pre" > </span>  
     }  
     m_visible_node->addChild(item);<span style= "white-space:pre" >  </span> //添加到visibleNode里面  
   
     m_items.insert(index,item);  
}


2、触摸事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
bool  GridView::onTouchBegan(Touch* pTouch,Event* pEvent){  
     Point p = Director::getInstance()->convertToGL(pTouch->getLocationInView());  
     if ( this ->getBoundingBox().containsPoint(p)){<span style= "white-space:pre" > </span> //判断是否触摸到  
         move_began = p;  
         return  true ;  
     }  
     return  false ;  
}  
   
void  GridView::onTouchMoved(Touch* pTouch,Event* pEvent){  
     CCLOG( "Touch Moved" );  
     move_ing= Director::getInstance()->convertToGL(pTouch->getLocationInView());  
     if (! this ->getBoundingBox().containsPoint(move_ing))  return ;  
   
     float  offset_y = move_ing.y - move_began.y; //计算出偏移量  
     CCLOG( "move_y:%f" ,offset_y);  
     m_visible_node->setPositionY(m_visible_node->getPositionY() + offset_y);  //visibleNode移动相应的偏移量  
     if (m_visible_node->getPositionY()<0){<span style= "white-space:pre" > </span> //头的判断(因为整个GridView的AnchorPoint是(0,0))  
         m_visible_node->setPositionY(0);  
     }  
     if (m_visible_node->getPositionY() > m_visible_node_posy_max){ //尾的判断。前面已经计算出最大可以上移的高度  
         m_visible_node->setPositionY(m_visible_node_posy_max);  
     }  
     if (m_visible_node_posy_max>0){<span style= "white-space:pre" >   </span> //这里主要是用在滚动条  
         float  delta_y = m_visible_node->getPositionY();  
         float  percent = delta_y/m_visible_node_posy_max;  
         scrollbar->setButtonPos(percent);  
     }  
     move_began = move_ing;  
}


3、滚动条

实现思路:
1)滚动条的大小由可见行数决定:滚动条高度=可见行数*每个Item的高度

2)滚动Button的大小由当前最大行数和可见行数决定:滚动Button的大小=可见行/最大行 * 滚动条高度

3)滚动条的位置由GridView当前位置和GridView最大可以上升的位置、滚动Button大小和滚动条大小决定

可以这样理解:

GridView上升高度/最大可以上升高度 =  Button下降高度/Button最大可以下降高度

其中,GridView的上升高度和最大上升高度可以直接获取,Button的最大下降高度= 滚动条大小-Button大小

因此,可以求出Button的下降高度。也就可以确定Button的位置


4、GridView主要用途

GridView可以用来做背包视图,或者一个简单的listView(需要设置列数为1)


最后,附上源码:注意要把那两个图片放到resource文件夹里面哦


源码下载:带滚动的表格GridView

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值