最近由于功能的需求,写了一个容器可变的滚动视图,文字长度也是从网上找的,
这个Demo的效果是这样的:
在一个指定大小的背景图上边,点击按钮,出现一条信息,(每次的信息长度不固定),这条信息出现在背景图的ScrollView上,当信息没有占满ScrollView的大小时,它是不可以滚动的,然后再点击按钮,再往这条信息的下方出现一条信息,最后当信息占满ScrollView时,会自动向上滚动,ScrollView的大小也会自动根据信息的长度而改变。
下面贴一下源码:
struct tagNoticeInfo
{
CCLabelTTF* labelNotice;
float fWidth;
};
.h文件
void loadScrollView();
void showNotice(std::string noticeStr);
CCLabelTTF* HorizontalSpacingANDVerticalSpacing(std::string _string,
const char *fontName,
float fontSize, float horizontalSpacing,
float verticalSpacing, float lineWidth);
//CCScrollView
CCLayer* m_layerScrollContain;
CCScrollView* m_scrollViewNotice;
std::vector<tagNoticeInfo> m_vctPriseInfo;
.cpp文件
void CBonusLayer::loadScrollView()
{
m_scrollViewNotice =
CCScrollView::create();
m_layerScrollContain =
CCLayer::create();//创建一个层,作为滚动的内容
m_layerScrollContain->setPosition(ccp(0,0));
m_layerScrollContain->setAnchorPoint(ccp(0,
0));
m_layerScrollContain->setContentSize(CCSizeMake(360,
500));
m_scrollViewNotice->setPosition(ccp(10,
25));
m_scrollViewNotice->setAnchorPoint(ccp(0,
0));
m_scrollViewNotice->setContentOffset(ccp(0,500-250));
m_scrollViewNotice->setViewSize(CCSizeMake(360,
500));//设置view的大小
m_scrollViewNotice->setContentSize(CCSizeMake(360,
500));
m_scrollViewNotice->setContainer(m_layerScrollContain);
m_scrollViewNotice->setBounceable(false);
m_scrollViewNotice->setDelegate(this);
m_scrollViewNotice->setTouchPriority(-200);
m_scrollViewNotice->setDirection(kCCScrollViewDirectionVertical);
m_spPriseList ->
addChild(m_scrollViewNotice);
}
void CBonusLayer::showNotice(std::string noticeStr)
{
//计算公告的位置
int count =
m_vctPriseInfo.size();
float height =
0;
for(unsigned
int i = 0; i < count; i++)
{
tagNoticeInfo NoticeInfo = (tagNoticeInfo)m_vctPriseInfo[i];
float width = NoticeInfo.fWidth;
height = height + width/340.0*40+40;//每一个公告的高度
}
tagNoticeInfo NoticeInfo;
NoticeInfo.labelNotice=
CCLabelTTF::create(noticeStr.c_str(),
"Arial", 32);
NoticeInfo.fWidth = NoticeInfo.labelNotice->getContentSize().width;
NoticeInfo.labelNotice =
HorizontalSpacingANDVerticalSpacing(NoticeInfo.labelNotice->getString(),
"Arial", 32,
1.5, 1,
340);
float fY = height + NoticeInfo.fWidth/340.0*40+80;
printf("fY is %f\n", fY);
//计算面板是否可以滚动,而且滚动的范围也要加以限制
if(fY <
500)
{
m_scrollViewNotice->setTouchEnabled(false);
NoticeInfo.labelNotice ->
setPosition(ccp(10,500-40
- height));
}
else
{
m_scrollViewNotice->setTouchEnabled(true);
m_layerScrollContain->setContentSize(CCSizeMake(360,
fY));
m_layerScrollContain->setPosition(ccp(0,0));
m_scrollViewNotice->setContentSize(CCSizeMake(360,
fY));
NoticeInfo.labelNotice ->
setPosition(ccp(10,(NoticeInfo.fWidth/340.0*40+40)));
float width =
0;
for(unsigned
int i = 0; i <
m_vctPriseInfo.size(); i++)
{
tagNoticeInfo NoticeInfo = (tagNoticeInfo)m_vctPriseInfo[i];
width = width + NoticeInfo.fWidth/340.0*40+40;
NoticeInfo.labelNotice ->
setPosition(ccp(10,fY-width+NoticeInfo.fWidth/340.0*40));
}
}
NoticeInfo.labelNotice ->
setAnchorPoint(ccp(0,0.5f));
m_layerScrollContain ->
addChild(NoticeInfo.labelNotice);
m_vctPriseInfo.push_back(NoticeInfo);
}
CCLabelTTF* CBonusLayer::HorizontalSpacingANDVerticalSpacing(std::string
_string, const char *fontName,
float fontSize, float horizontalSpacing,
float verticalSpacing, float lineWidth)
{
CCArray* labelTTF_arr =
CCArray::create();
int index =
0;
int index_max =
strlen(_string.c_str());
bool is_end =
true;
while (is_end) {
if (_string[index] >=
0 && _string[index] <=
127) {
std::string englishStr = _string.substr(index,1).c_str();
const
char* englishChar = englishStr.c_str();
labelTTF_arr->addObject(CCLabelTTF::create(englishChar, fontName, fontSize));
index+= 1;
}
else{
std::string chineseStr = _string.substr(index,3).c_str();
const
char* chineseChar = chineseStr.c_str();
labelTTF_arr->addObject(CCLabelTTF::create(chineseChar, fontName, fontSize));
index+= 3;
}
if (index>=index_max) {
is_end=false;
}
}
//以上步骤是根据ASCII码找出中英文字符,并创建成一个CCLabelTTF对象存入labelTTF_arr数组中。
//下面创建的原理是在CCLabelTTF对象上添加子对象CCLabelTTF,以此组合成一句话,以左上角第一个字为锚点。。
CCLabelTTF* returnTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(0);
returnTTF->setColor(ccc3(116,
0, 0));
float nowWidth = returnTTF->getContentSize().width;
CCLabelTTF* dangqiangTTF = returnTTF;
CCLabelTTF* lineBeginTTF = returnTTF;
int arr_count = labelTTF_arr->count();
for (int i=1; i < arr_count; i++) {
CCLabelTTF* beforeTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(i);
beforeTTF->setColor(ccc3(116,
0, 0));
beforeTTF->setAnchorPoint(ccp(0,
0.5));
nowWidth+=beforeTTF->getContentSize().width;
if (nowWidth >= lineWidth) {
nowWidth = returnTTF->getContentSize().width;
dangqiangTTF = lineBeginTTF;
beforeTTF->setPosition(ccp(0, -dangqiangTTF->getContentSize().height*0.5-verticalSpacing));
lineBeginTTF = beforeTTF;
}else{
beforeTTF->setPosition(ccp(dangqiangTTF->getContentSize().width+horizontalSpacing,
dangqiangTTF->getContentSize().height*0.5));
}
dangqiangTTF->addChild(beforeTTF);
dangqiangTTF = beforeTTF;
}
return returnTTF;
}