CCTableView详解

CCTableView是参照UITableView来写的,因此其对于tablecell的处理基本原理也是相通的。

在CCTableView的头文件中声明了三个类
1.  class   CCTableViewDelegate
2.  class   CCTableViewDataSource
3.  class   CCTableView :   public   CCScrollView ,   public   CCScrollViewDelegate

使用时需要继承CCTableViewDelegate和CCTableViewDataSource这两个类,实现其中的下列三个方法:
1、 响应table触摸事件的方法,其中 CCTableView   *   table为包含给定cell的table, CCTableViewCell   *   cell为触摸到的cell。

virtual   void   tableWithcellTouched ( CCTableView   *   table ,   CCTableViewCell   *   cell );
常常在该方法里取得cell的idx,cell-> Getidx()

2、 返回给定table中cell的数量。
virtual   int   numberOfCellsInTableView ( CCTableView   * table );
比如你想要建立一个包含10个cell的table,可以return 10。

3、 对于给定idx的cell实例变量进行初始化和更新
virtual   CCTableViewCell   *   tablecellAtIndex ( CCTableView   * table ,   int   idx );
该方法主要用来初始化cell和cell包括的内容,并负责更新该cell。继承后的写法一般如下:
{
    CCTableViewCell   *   cell ;
    cell   =   table -> dequeueCell ();
    if ( ! cell {
          cell   =   new   CCTableViewCell ;
          CCNode   * node   =   CCNode :: node ();
         // 初始化cell信息
          cell -> Setnode ( node );
    }
    CCNode   * node   =   cell -> Getnode ();
   // 更新cell的内容
    return   cell ;
}

===================Everybody, everybody wants to love===================

可见CCTableView是继承自CCScrollView的,但是在CCScrollView之上做了一些优化。
其中最赞的一点即tableview对cell的内存管理机制,这得益于上面tablecellAtIndex方法中的dequeueCell()方法,我们来详细介绍一下:
cell   =   table -> dequeueCell ();

dequeueCell的方法如下:
CCTableViewCell   *   CCTableView :: dequeueCell ()
{
    CCTableViewCell   * cell ;
    _evictCell (); // 将不在显示区域的cell放入一个临时的vector中
    if  ( cellsFreed_ . size ()  ==   0 ) // cellsFreed即为那个临时的vector,其中保存了当前不在显示区域的cell
    {
        cell   =   NULL ;
        return   cell ;
    }
    else
    { // 如果cellsFreed非空,则取出其中的一个cell来复用
        cell   =   cellsFreed_ [ 0 ];
        cellsFreed_ . erase ( cellsFreed_ . begin ());
        return   cell ;
    }
   
}


其中的根据scrollView的偏移来计算当前显示的tableview中可见cell的算法可以在 _evictCell ();中看到。

因此一般情况下,如果当前屏幕中有N个可见cell,那么tableView会创建N+2个cell,其中在头部和尾部之外都还有一个“预加载”的cell。

但是这只是外部表现出来的,就像这样
CCTableView详解1

当向下移动table的时候,cell0会出现。cellsFreed_中的数据会被给到cellsUsed_内,因此预加载的cell内存地址和当cell可见时候的内存地址是不一样。
预加载的cell在地理位置上也不像图中所见的那样,在cell1上方。

最近遇到的一个bug就是点击cell中的图片,显示图片的基本信息。使用判断触摸点是否在图片内部的方法。
CCPoint   point   =   convertTouchToNodeSpaceAR ( touch );

在cell和cell中间的位置上,有时候点击会触发预加载的cell内图片的ccTouchBegan方法,因为预加载的cell内图片的触摸优先级和普通的可见的cell中图片的触摸优先级是一样的,我们将该图片封装为一个单独的类。

为此想了很多方法,如何区分预加载的cell和已经加载的cell。
最终我是这么做的,在ccTouchBegan中加入如下代码:
if  ( dynamic_cast <</span>CCNode *>(this->getParent())) {
   if (dynamic_cast<</span>CCLayer *>(this->getParent()->getParent())) {
         // 为已经加载的cell,执行接下来的判断是否在图片内部的方法
       CCLog("this->getParent->getParent");
   } else {
         // 为预加载cell,直接返回
       return true;
   }
}

CCTableViewCell继承自CCObject方法,由于在tableAtIndex中,有了cell->SetNode(node);的代码,所以判断parent的时候不能判断为CCTableViewCell*,而应该为CCNode*
CCTableView继承自CCScrollView,最上层继承自CCLayer,因此 ( this -> getParent () -> getParent ())时,应该判断是否为CCLayer*。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值