上周在公司的项目中实现了一个功能:利用TableView制作二级菜单。大概意思就是,首先用TableView制作了一个菜单列表,然后再点击某个cell则展出另外一个菜单,那个菜单也是利用tableView实现的,这能否说是实现二级菜单的效果呢?要是知道制作动态gif图就好了,就可以直观的把这个效果展示出来。
自我感觉这个功能是挺重要的,因为有的时候在游戏中经常有需要用到二级菜单,比如说做一个战役副本-副本里面有小关卡(项目做了这个),利用这个做感觉效果就会不错;另外有一些任务功能,一级任务-展开二级任务。当然,这有点扯远了,之前在做另外一个项目的时候,就在想这种功能该如何做,因为我觉得这个效果以后肯定会要用到的,结果就真说中了,这次要用了,而且要我去做。一开始感觉自己做不来,所以感觉有压力,后来真开始做了,头一天构思了以下该如何实现,也就是星期四,第二天就着手开始做了,上午做了一些准备。中午老大问我啥时候能做完,那个时候我都心里没底,因为开发任务是到周五要做完,所以我只能说,我试试看。下午着手去做了,做了一个下午,功能基本实现了,周六加班,再把效果调整了一下。做完之后我有感而发,认为:人还是有潜力的。因为一开始我不觉得我能做好,一直认为可能要转手交给同事去完成,而现在我做好了,所以认为还是有点潜力的~!
OK,回到主题。项目的代码在公司,明天把上相关的示例代码,现在先主要记录下自己的思路。
代码上传ing...
一开始,自己觉得最纠结的点在于如何移动各个cell,并再将各个cell移动回来(即当我们点击菜单按钮,相关cell上移下移,中间空出来展示二级菜单)。因为我们移动到的点是固定的(可以认为是tableview的viewsize的顶部和底部(即.height 和 0 的位置,我觉得也只需要移动到这个位置即可,当然这里的顶部的话还需要减去一个cell的高度,因为我们需要将那个cell显示出来)),这样的话当我们点击某个按钮,效果应该是点中的这个cell上移(这个cell之上的各个cell都要上移,之下的下移)到tebleview的顶部,在上移的过程中展开二级菜单,最初我想既然是移动到固定的两个点,那么直接可以用moveTo这个动作来实现,后来一想不行啊,移动过去了我怎么再移动回来啊,我还得记住移动前的位置,再一个一个移动回来,那么算那个位置好麻烦啊(我也不知道怎么算。。。);
否定了之前的那个想法之后我想用moveBy比较好(其实我一开始就用了这个动作实现了一个简单的demo),因为moveBy是移动相对距离,然后可以调用它的reverse方法便捷的再移动回来,这个很好的适应了我的要求,当时为啥做出了demo还会去想用moveTo,主要是因为moveBy这个相对距离的问题,每次都得相对移动到顶部和底部两个点,这个相对距离该怎么算呢?所以我才想了是不是要用moveTo这个动作,其实只要将moveBy的这个相对距离算好了,那么这个功能就差不多实现了。
所以,第一天我大概的构思了一下之后,第二天上班我就在想怎么算这个相对距离。当然在中午老大问我之前我都没想好怎么算(对引擎的相关功能还是理解的不够透彻啊,大牛的话应该是拍腿一下,就OK了吧),既然咱是小喽啰,那么我就得想个半天,然后老大一问我进度怎么样了,再我回答完我要试试我的一个想法之后,我想出了改怎么去算这个相对距离了(看来有的时候还是需要一点压力的)---转换成世界坐标咋样?
有了想法之后,我立马将想法付诸于行动了:得到我点击的这个cell,得到它的坐标然后我转换为世界坐标(起初我不知道这个坐标是不是有用的,一开始我是将转换为世界坐标和节点坐标两个都使用了,通过打印log我去试了这两种方法(傻人傻方法吧),看打印出来的信息,我发现转换成世界坐标是有用的),转换为了世界坐标,那么我就知道了cell相对于tableview的viewSize的位置,就能算出这个相对距离了,而其他的cell的相对移动距离也就这么算出来了。得到了这个相对移动距离,那么点击某个按钮然后这个按钮与其他按钮的便能移动到相应的位置,然后再展开二级菜单,那么我们需要的功能就实现了~!
大致的示例代码:
for (int i = 0; i<10; ++i) { auto sp = SelectButton::createWith("xx.png", "xx.png",StringUtils::format("%d",i).c_str()); sp->setTag(i); sp->setTouchArea(_touchArea);// sp->setClickTimeControl(true); buttonMap.insert(i, sp); }这里我的想法是将各个一级菜单加入到一个Map中进行管理;
重点在于点击cell后,tableview的反应:
unFold = !unFold; auto idx = cell->getIdx(); auto c = buttonMap.at(clickIdx); log("cell,cell idx = %d pos = %.1f %.1f",clickIdx,c->convertToWorldSpace(c->getPosition()).x,c->convertToWorldSpace(c->getPosition()).y); if (unFold)//展开 { beforeUnfoldPos = c->convertToWorldSpace(c->getPosition()); //这里根据tableview的viewsize去算相对移动距离 moveDis.y = nTableView_Height - beforeUnfoldPos.y + _tableViewPos.y; log("dis = %.1f",moveDis.y); //点击后tableview不可以拖动(这里更改了引擎源码) _tableview->setCanMove(false); if (idx < buttonMap.size())//这里就是用Map进行管理的好处咯 { for (auto sp:buttonMap)//思路就是将点击的这个cell的tag值与其余的值进行比较 { if (sp.second->getTag()>=clickIdx)//比它大或者是自己 则上移 { sp.second->runAction(MoveBy::create(0.4f,Point(0, moveDis.y))); } else { sp.second->runAction(MoveBy::create(0.4f,Point(0, -nTableView_Height+moveDis.y))); } } } } else//这是第二次点击之后,所有的cell回到原来的位置 {// log("dis = %.1f",moveDis.y); if (idx < buttonMap.size()) { for (auto sp:buttonMap) { if (sp.second->getTag()>=clickIdx) { sp.second->runAction(MoveBy::create(0.4f,Point(0, -moveDis.y))); } else { sp.second->runAction(MoveBy::create(0.4f,Point(0, nTableView_Height-moveDis.y))); } } } _tableview->setCanMove(tableViewCanMove); } _selectBtn = nullptr;这就是这个功能实现所需要的主要代码,因为这个涉及到了公司项目,所以以简化的来说说事,回家后有时间自己再弄个具体的看看~!
自己写个demo,然后将功能具体的实现一遍,记录下来!~