Se référer : cocos2dx/extensions/GUI/CCScrollView/CCScrollView.cpp
Plus précisément CCScrollView::minContainerOffset
y CCScrollView::maxContainerOffset
CCScrollView
travaille en Coordonnées OpenGL (par opposition à coordonnées de la fenêtre ) - les valeurs sont relatives à (gauche, bas), l'axe Y positif allant vers le haut. Il convient également de tenir compte du positionnement de la vue de défilement et de la fonction conteneur sont ancrés ( CCNode::setAnchorPoint
) à (gauche, bas).
Lorsque vous faites défiler le contenu vers le bas (déplacez/tirez le contenu vers le haut pour voir le contenu sous la coupure/le clip), vous voyez le contenu sous le bord inférieur de l'écran mais il rebondit dès que vous relâchez le toucher/tirer parce que maxContainerOffset
retours (0, 0)
et vous venez d'essayer de passer à une compensation de contenu positive.
Le diagramme montre l'état de la écran de défilement et le conteneur lorsqu'ils sont créés/initialisés. Il s'agit de l'état ou des coordonnées auxquels il faut "penser" lors de la mise en place et du positionnement des éléments enfants y conteneur . Le rectangle gris (à gauche, en bas) montre la zone valide pour le défilement de l'image. conteneur . Imaginez que le point d'ancrage du conteneur se déplace à l'intérieur de celui-ci.
Pour voir le conteneur défiler vers le haut au départ (ce à quoi on s'attend lorsqu'on travaille en coordonnées de la fenêtre ), réglez le décalage du contenu en conséquence (immédiatement après l'avoir configuré). Vous obtiendrez ainsi les résultats/comportements attendus.
scrollView->setContentOffset(ccp(0.f, (scrollViewHeight-scrollContainerHeight)), false);
Un exemple plus complet se trouve dans le code édité ci-dessous.
-
Une "solution" pour permettre le défilement dans les coordonnées de la fenêtre (axe Y positif vers le bas) pourrait être d'ajuster l'extension, ce qui nécessiterait de reconstruire la bibliothèque cocos2dx et affecterait tous les projets (même les autres exemples de code que vous pouvez essayer).
/*
// (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);
}
*/
-
A moins intrusif piratage est de mettre à l'échelle le ScrollView à -1 et l'instance enfants de la nœud de conteneur également à -1. Vous devez également repositionner le nœuds enfants en tenant compte de l'échelle inverse. Le résultat de la mise à l'échelle aux deux niveaux est le contenu ( nœuds enfants ) sont vus directement (et non à l'envers). Le résultat de la mise à l'échelle du ScrollView à -1 est que le défilement se déroule pour vous dans la direction attendue. Notez cependant que cette "correction" inversera également le défilement sur l'axe des X et qu'elle est donc sólo convient si vous souhaitez faire défiler verticalement ( 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);
Notez également que les deux correctifs mentionnés ci-dessus sont mutuellement exclusifs , faire no appliquer à la fois .
Réponse maintenant aussi sur le forum cocos2d-x.