问候Stackoverflow,
我目前正在尝试将滚动菜单实现为我正在开发的cocos2d-x游戏。问题是这些项目正朝着我想要的相反方向滚动。例如,如果我将手指从屏幕底部拖到顶部,精灵将弹回原位。
如果我将手指从顶部拖到底部,精灵将跟随我的手指(直到它到达边界)。
这是我的代码:
/////////////////////
//SCROLL VIEW + LAYER
CCLayer *layer = CCLayer::create();
layer->setContentSize( CCSizeMake( winSize.width, winSize.height ) );
layer->addChild( menu );
scrollView = CCScrollView::create();
scrollView->retain();
scrollView->setContentSize( CCSizeMake ( layer->getContentSize().width, layer->getContentSize().height ) );
scrollView->setDirection( CCScrollViewDirectionVertical );
scrollView->setPosition( ccp( 0,0 ) );
scrollView->setContainer( layer );
this->addChild(scrollView);
scrollView->setContentOffset( CCPointZero );
非常感谢任何建议或帮助。如果您还有其他方法可以使用其他方法创建滚动菜单,我很乐意听到。
谢谢!
祝你好运 安德烈亚斯
答案 0 :(得分:8)
参考:cocos2dx/extensions/GUI/CCScrollView/CCScrollView.cpp
具体为CCScrollView::minContainerOffset
和CCScrollView::maxContainerOffset
CCScrollView
适用于 OpenGL坐标(与窗口坐标相对) - 值相对于(左,下),正Y轴向上。另外,请记住滚动视图的定位,容器锚定(CCNode::setAnchorPoint
)到(左,下)。
当您向下滚动(向上移动/拉动内容以查看剪切/剪辑下方的内容)时,您会看到屏幕下边缘下方的内容,但是当您放开触摸/拖动时它会弹回,因为maxContainerOffset
返回(0, 0)
,您刚尝试转移到正内容偏移量。
该图显示了 scrollview 和容器在创建/初始化时的状态。这是设置和定位子元素和容器时“思考”的状态或坐标。灰色矩形(左侧,下方)显示滚动容器的有效区域。想象一下容器的锚点在其内部移动。
要查看容器滚动到顶部以开始(在窗口坐标中工作时所期望的那样),请相应地设置内容偏移(在设置之后立即)。这将给出预期的结果/行为。
scrollView->setContentOffset(ccp(0.f, (scrollViewHeight-scrollContainerHeight)), false);
更完整的示例位于下面的编辑代码中。
允许在窗口坐标(正Y轴向下)中滚动的“修复”可能是调整扩展名,这需要您重建cocos2dx库并影响所有项目(甚至其他项目)您可以尝试的示例代码。)
/*
// (StackOverflow Post Edit: This hack is not required.)
CCPoint CCScrollView::maxContainerOffset()
{
// Default CCPointZero;
return ccp(0.0f, m_pContainer->getContentSize().height*m_pContainer->getScaleY() - m_tViewSize.height);
}
CCPoint CCScrollView::minContainerOffset()
{
// Default Y = m_tViewSize.height - m_pContainer->getContentSize().height*m_pContainer->getScaleY();
return ccp(m_tViewSize.width - m_pContainer->getContentSize().width*m_pContainer->getScaleX(),
0.f);
}
*/
较少侵入性 hack ,是将 ScrollView 实例扩展为-1和子项容器节点的也是-1。您还必须重新定位子节点,同时考虑反比例。两个级别的缩放结果是内容(子节点)被直接观看(未翻转)。将 ScrollView 缩放为-1的结果是滚动在预期的方向上发生。请注意,虽然此“修复”也会在X轴上翻转滚动,因此如果您希望垂直滚动( CCScrollViewDirectionVertical
),则仅是合适的。
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCLayer* scrollContainer = CCLayer::create(); // Container for the scroll view
scrollContainer->setAnchorPoint(CCPointZero); // CCScrollView does this too when it's set as the container.
// Content for the container
CCSprite *tallContentA = CCSprite::create("TallContentA.png");
tallContentA ->setPosition(ccp(winSize.width*0.5f, winSize.height*0.9f));
CCSprite *tallContentB = CCSprite::create("TallContentB.png");
tallContentB ->setPosition(ccp(winSize.width*0.5f, winSize.height*0.1f));
scrollContainer->addChild(tallContentA, 2);
scrollContainer->addChild(tallContentB, 2);
float scrollContainerHeight = tallContentA->getContentSize().height + tallContentB->getContentSize().height;
scrollContainer->setPosition(CCPointZero);
scrollContainer->setContentSize(CCSizeMake(winSize.width, scrollContainerHeight*1.05f));
// Set up scroll view
CCScrollView* scrollView = CCScrollView::create(winSize, scrollContainer);
scrollView->setPosition(CCPointZero);
scrollView->setDirection(CCScrollViewDirectionVertical);
// ScrollView initializes at the (left, bottom). The container also gets positioned relative to that and goes Y-up.
// Pre-set it to the value CCScrollView::minContainerOffset will return when it's scrolled to the top
// (note, this is a negative number, indicating the touch moving downwards, i.e. it's pre-scrolled such that the top of the content is visible when we begin)
scrollView->setContentOffset(ccp(0.f, (winSize.height-scrollContainerHeight*1.05f)), false);
/*
// (StackOverflow Post Edit: This hack is not required.)
// Hack: CCScrollView's maxContainerOffset is (0, 0) and minContainerOffset is (difference between view and content size which is negative)
// It's designed to be (left, bottom) based and positive scrolling means showing stuff above the top of the screen.
// Since we're using it in terms of Window coordinates ((left, top) based), we scale the scroll view
// and it's container's children by -1 and position the children differently
// (eg. Y position winSize.height*0.1f was changed to winSize.height*0.9f)
// We can't just set the scroll view's Y scale to -1 because CCNode::getScale asserts that X and Y scale must be the same.
scrollView->setScale(-1.f);
tallContentA->setScale(-1.f);
tallContentB->setScale(-1.f);
*/
addChild(scrollView);
另请注意,上面提到的两个修补程序是互斥,不应用两者。
Answer现在也在cocos2d-x论坛上。
答案 1 :(得分:3)
@Zennichimaro,
@ PAT的答案是正确的,本质上是简化版
考虑到这一点,请注意3件事情很重要:
CCScrollView::setViewSize()
- 你显然错过了这个,它必须是你的可视空间的宽度和高度(蓝色的盒子,我认为这是你的整个windowSize,如果你想全屏) / p>
CCScrollView::setContentSize()
- 这与setContentOffset不同,看起来你把它误解为setContentOffset,无论如何,这应该设置为整个容器的大小(红色框,你的可能是ccp(windowSize.width,2496.0f)
)
CCScrollView::setContentOffset()
- 如果你想定位它以使最顶部最初可见,最小值和最大值由答案中的小灰色矩形框指定(灰色框,你的可能是ccp(0.0f, windowSize.height-2496.0f)
)
答案 2 :(得分:3)
较短的答案是:
scrollView->setContentOffset(scrollView->minContainerOffset());
由于锚点位于左下角,因此初始偏移量不为零,而是负数。
答案 3 :(得分:0)
如果有人想在mmo游戏聊天表中创建滚动视图(将消息添加到底部并自动滚动到底部),那么也许有人会觉得这很有用:
我的ChatTableView.h的部分代码
//tableView dataSource is vector of strings
class ChatTableView :public Layer, public TableViewDataSource, public TableViewDelegate
{
public:
vector<string> n_msglist;
TableView* pTableView;
void addMsg(string text);
private:
};
//part of the code of my ChatTableView.cpp
void Init(){
pTableView = TableView::create(this, VisibleRect::getVisibleRect().size, NULL);
pTableView->setDirection(ScrollView::Direction::VERTICAL);
pTableView->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);
pTableView->setDelegate(this);
pTableView->setBounceable(false);
}
void ChatTableView::addMsg(string text){
n_msglist.push_back(text); //adds string to vector
pTableView->reloadData(); //reloads data with newly updated vector and scroll back to top
pTableView->setContentOffset(pTableView->maxContainerOffset()); //scrolls to bottom
}