欢迎光临Software MyZone,有问题可留言或到站点论坛发帖,争取第一时间帮忙解决 || 站点论坛:火龙论坛 || 淘宝小店:应小心的易淘屋 【欢迎大家提建设性意见】

CCScrollView及CCScrollView与CCMenu问题【终结篇】

本文为firedragonpzy原创,转载务必在明显处注明: 转载自【Softeware MyZone】原文链接: http://www.firedragonpzy.com.cn/index.php/archives/3111

欢迎热爱编程的朋友们参与到cocos2d-x编程中,为了给大家提供良好的交流环境,网站以开启QQ群 Software MyZone:66202765(群号,欢迎加入,若满,请加1群) Software MyZone 1群(2dx):286504621 【加群请写:Software MyZone或者是firedragonpzy】 群论坛:火龙论坛正试运营阶段,欢迎大家多提些建设性意见……

近期一个项目,使用了CCScrollView,发现很多地方不尽人意,接下来我与大家分享一下CCSCrollView。站中也有几篇讲解了CCScrollView ,但是我感觉比较零碎,现在整体汇总一下: 下面是CCScrollView使用过程中会遇到的问题: 1、不同版本的使用方法 2、有关CCScrollView的缩放 3、手势缩放的时候,如果缩放到了和屏幕一样的尺寸,不同的缩放基准点会导致屏幕不同的地方出现屏幕黑背景 4、缩放后的bounce问题 5、如果容器中含有CCMenu,优先级的处理问题以及事件的吞并下面一一讲述:

关于第一条:不同版本的使用方法

在2dx2.0.2的时候,使用是一种方法,后来我用了2.0.4,源代码到2.0.4上之后显示不全了,主要原因是:


CCScrollView* CCScrollView::create()
{
 CCScrollView* pRet = new CCScrollView();
 if (pRet && pRet->init())
 {
 pRet->autorelease();
 }
 else
 {
 CC_SAFE_DELETE(pRet);
 }
 return pRet;
}

使用create()方法创建的话,在init()函数中默认设置了个200*200的区域大小,而这个区域正好是CCScrollView的显示区域


bool CCScrollView::init()
{
 return this->initWithViewSize(CCSizeMake(200, 200), NULL);
}

有关详细CCScrollView的使用大家可以参考此文:CCScrollView的使用 如果你使用了vs开发的话,可能会遇到link库的问题,详细可以参考此文:error LNK2019: 无法解析的外部符号 “public: static class cocos2d::extension::CCScrollView

关于第二个问题:有关CCScrollView的缩放

有关缩放的,在缩放的地方使用setZoomScale方法,这个方法里的缩放是这么实现的:

 m_pContainer->setScale(MAX(m_fMinScale, MIN(m_fMaxScale, s)));
但是其中的m_fMinScale=m_fMaxScale=1  而且这两个没有提供接口改变,所以大家缩放的时候会出现bug,我明明使用了setZoomScale方法,我的怎么不缩放呢?呵呵,很多人就会认为是bug,如果使用引擎自带的源码,你在缩放的时候需要m_pContainer->setScale(2)和CCScrollView的实例scrollView->setZoomScale(2)一起使用,这样就可达到缩放效果了,如果只想调用setZoomScale,大家可以使用我的FDScrollView,关于FDScrollView,大家可以参考此文获取。FDScrollView:CCScrollVIew Bug修改版:FDScrollView,使用FDScrollView如果进行缩放,只需要调用setZoomScale即可。

关于第三条:手势缩放的时候,如果缩放到了和屏幕一样的尺寸,不同的缩放基准点会导致屏幕不同的地方出现屏幕黑背景

这个需要分开讲述下:首先说一下CCScrollView缩放时候的基准点问题,如果你使用setZoomScale缩放的话,它的基准点是你缩放两指的中心点,如果使用m_pContainer的话自然是你容器的锚点。
大家明白缩放的基准点之后,再说一下缩放过程中遇到的问题。假设我们设置的容器m_pContainer的锚点是左下角,我们移动CCScrollView,将可见区域【区域左下角】移动至屏幕中心,我们进行缩放,如果使用容器缩放,此时CCSCrollView可见区域的左下角还是在屏幕中心,那整个屏幕四分之三都是黑屏幕,CCScrollView只占屏幕的四分之一,若使用setZoomScale就更不用说了,连四分之一都不到。这,不是我们想要的效果。想必大家都玩过愤怒的小鸟吧,无论怎么缩放,他都会讲CCscrollView的显示区域填充满整个屏幕 ,即使是上述情况,依然满屏显示。这个问题,我的FDScrollView已经解决,大家可以使用FDScrollView来解决这个问题。

关于第四条:缩放后的bounce问题

先描述一下这个bounce问题,如果我不进行缩放,bounce的距离是没有问题的。如果我进行了缩放,你往右上滑动CCScrollViewbounce的距离是没有问题的,如果你往左下滑动CCScrollView,这时bug就出现了,bounce的距离不再和你往右上角滑动的距离一致了,它会根据你的缩放发生变化。
关于这个bounce问题,我感觉挺纠结的,其实在实际应用的,大家会把这个bounce设置的很小,甚至不用,仔细观察愤怒的小鸟,它的bounce是很小的,我的FDScrollView已经设置很小了,大家若是想设置bounce的值,可以使用FDScrollView的#define INSET_RATIOFD 0.02 。如果你改源码中的INSET_RATIO会出现bug。因为bounce问题没有完全解决,再鉴于bounce在实际 应用中bounce的距离肯定会很小,所以我的FDScrollView直接屏蔽了bounce。关于应用中的bounce问题,是不是真的很小,大家可以看看愤怒的小鸟。

关于第五条:如果容器中含有CCMenu,优先级的处理问题以及事件的吞并

解决这个办法你可以封装CCMenu,改变其优先级,也可以封装CCScrollView,改变其优先级,改变优先级大家可以参考:使用CCScrollView后,如果有菜单,不能拖动【优先级问题】问题解决
(但是如果你使用了ccbi?能行吗?)虽然这个问题解决了,但是随之而来的事件处理问题就又来了。
你点击在menu上滑动,当手指离开menu的时候,它会触发menu的事件,这个很纠结。
关于这个问题,大家可以如下处理:
将CCMenu的优先级调整到1,在CCScrollView的父节点添加目标代理,在began和ended事件里获取两个值作为距离:distance,然后到menu的事件里进行这个distance距离的判断:是否进入menu应该处理的事件。这样就完全ok。
但是最纠结的问题是你的校准,CCScrollView的校准只是左右校准,如果滑动结束时,在两页之间这时候大家就需要校准。
问题来了,这个校准你在什么时候触发,如果是点击menu移动,在进行完了distance判断时候确定是移动,不触发menu的点击事件,你肯定调用校准,但是如果你点击非menu区进行移动呢,这时候也要校准。大家会考虑,我在CCScrollView父节点的ended事件校准不就好了吗?是吗?答案是否定的,不行,因为优先级的问题会出现不尽人意的效果,这时候你就需要这么处理校准:首先校准在menu里面处理一次,然后在标准代理的事件里处理一次,看清楚了,是标准代理的事件,不是咱们处理距离的目标代理事件。好了,问题基本结束,累死了,我可怜的周末啊……
补充条目:CCScrollView在上级容器缩放后响应触摸区域错误的问题
推荐:滑动使用CCTableView,如果有类似CCMenu功能的使用CCControllButton代替……
此文年前巨献,提前祝大家:过年好……
  1. 首先校准在menu里面处理一次,然后在标准代理的事件里处理一次,看清楚了,是标准代理的事件,不是咱们处理距离的目标代理事件 这个没理解

    • ccmenu会吞并事件的,你在menu上滑动和在非menu区滑动看看效果,差强人意。所以我进行了两次校准。一次是在menu触发的事件中,一次是在标准代理的事件中处理的。貌似目标代理和标准代理都有的时候, 先按照优先级处理目标代理事件然后处理标准代理事件。。。