[Cocos2d-x] How to place the innerContainer always top of the view of Content in ScrollView

Hello.

I created a loop for creating multiple Sprites and add them to ScrollView. Therefore, I need to adjust the innerContainerSize according to the number of Sprites created.
When the value of innerContainerSize is smaller than contentSize, the innerContainer will be placed at bottom of the contentSize.

Do anyone know how to place the innerContainer to the top of the view of Content in ScrollView?

This is my implementation:

std::string input = a;
    std::vector vecOfFriend = split(input, ',');
    int numOfFd = vecOfFriend[0].c_str()[0] - 48;
    // Scrolling Menu
    ui::ScrollView *scrollView = ui::ScrollView::create();
    scrollView->setDirection(ui::ScrollView::Direction::VERTICAL);
    scrollView->setContentSize(Size(930, 1390)); // 930, 1390
   // scrollView->setInnerContainerSize(Size(1280, (2000/7) * 7));
    scrollView->setBounceEnabled(false);
    //scrollView->setBackGroundImage("bg6.png");
    scrollView->setPosition(Vec2(95,520));
    scrollView->setScrollBarEnabled(false);
    
    this->addChild(scrollView);
    
    int i;
    int index;
    for (i = 1, index = 1; i <= numOfFd * 3; i = i + 3, index++) // 4,Joe,JL,0,Ivan,IS,0,NEO,NY,0,Nic,NN,0
    {
        cocos2d::ui::Button* fd = cocos2d::ui::Button::create("testlist.png", "testlist.png");
        Label* fdID = Label::createWithTTF(vecOfFriend[i + 1], "NotoSansCJKtc-Regular.otf", 50);
        fdID->setPosition(Vec2(350,130));
        fd->addChild(fdID, 0);
        Label* fdName = Label::createWithTTF(vecOfFriend[i], "NotoSansCJKtc-Regular.otf", 50);
        fdName->setPosition(Vec2(350,60));
        fd->addChild(fdName, 0);
        Sprite* status = Sprite::create("eye.png"); // vecOfFriend[i+2]
        status->setPosition(Vec2(900,90));
        fd->addChild(status, 0);
        fd->setPosition(Vec2(scrollView->getContentSize().width / 2 ,200 * numOfFd + 110 - (200 * index))); // 1850
        log("Height: %f", (fd->getContentSize()).height);
        fd->addTouchEventListener(CC_CALLBACK_2(Fdpage::touchEvent,this));
        scrollView->addChild(fd);
        
       
        auto fdSeparator = Sprite::create("LongBarTT.png");
        fdSeparator->setPosition(Vec2(scrollView->getContentSize().width / 2 ,200 * numOfFd + 110 - (200 * index) - 100));
        scrollView->addChild(fdSeparator);
        log("Height: %f", fd->getContentSize().height);
    }
    scrollView->setInnerContainerSize(Size(1280, 200 * numOfFd)); // 1280, 200 * numOfFd

Many Thanks!!!

I don’t quite follow this. Can you explain differently.

@joelam500 Showing some screenshots of desired output and actually output would help in understanding what is it you’re asking for.

Thanks for replying.
Current output:

Expect output:

I see now. top versus on top. Thank you for clarifying.

Double check your setPosition statements. That’s where the problem probably is. The scrollview has a contentHeight. Start with that value and subtract each “row”s height that you are adding.

I believe cpp-tests has an example too

That is really odd. Try setting the background color of the inner container in order to see what size it actually is, and where it’s located within the ScrollView. You can do something like this:

auto innerContainer = scrollView->getInnerContainer();
innerContainer->setBackGroundColorType(cocos2d::ui::Layout::BackGroundColorType::SOLID);
innerContainer->setBackGroundColor(Color3B::RED);

At least then you’ll be able to see if the container is actually out of position or there is something wrong with the dimensions of the inner container etc…

I already tried your solution to fix the problem. The output is on top of the Content now. But when the Sprites exceed the contentSize, there will have some Sprites missing.

The code is provided below:

int i;
    int index;
    for (i = 1, index = 0; i <= numOfFd * 3; i = i + 3, index++) // 4,Joe,JL,0,Ivan,IS,0,NEO,NY,0,Nic,NN,0
    {
        fd = cocos2d::ui::Button::create("testlist##.png", "testlist##.png");
        Label* fdID = Label::createWithTTF(vecOfFriend[i + 1], "NotoSansCJKtc-Regular.otf", 50);
        fdID->setPosition(Vec2(350,130));
        fd->addChild(fdID, 0);
        Label* fdName = Label::createWithTTF(vecOfFriend[i], "NotoSansCJKtc-Regular.otf", 50);
        fdName->setPosition(Vec2(350,60));
        fd->addChild(fdName, 0);
        Sprite* status = Sprite::create("eye.png"); // vecOfFriend[i+2]
        status->setPosition(Vec2(900,90));
        fd->addChild(status, 0);
        // fd->setPosition(Vec2(scrollView->getContentSize().width / 2 ,200 * numOfFd + 110 - (200 * index))); // 1850
        fd->setAnchorPoint(Vec2(0.5, 1));
        fd->setPosition(Vec2(scrollView->getContentSize().width / 2, scrollView->getContentSize().height -
                             (fd->getContentSize().height * index)));
        log("Height: %f", (fd->getContentSize()).height);
        fd->addTouchEventListener(CC_CALLBACK_2(Fdpage::touchEvent,this));
        scrollView->addChild(fd);
        
        log("Height: %f", fd->getContentSize().height);
        
    }
    
    scrollView->setInnerContainerSize(Size(1280, fd->getContentSize().height * numOfFd));

I know you have the solution. I use something like this

 frontGunScrollLayer->setInnerContainerSize(cocos2d::Size(0,(numberOfButtons * BTN_HEIGHT_CLOSED));

I hope this helps

Thanks for replying.
May I know what is BTN_HEIGHT_CLOSED?
Thank you.

I have custom buttons that can change its Content size. When the buttons are open they have a different size as to when they are closed. So that is just the height of the button.

I see. I also set the innerContainerSize as

scrollView->setInnerContainerSize(Size(1280, fd->getContentSize().height * numOfFd));

Currently, when I add are buttons that are exceeded the height of scrollView, all buttons are gone except the first one. I am very confused where the problem is. :thinking:

could you share a video of the output.

Hi @joelam500,
I faced the exact same issue only but two weeks ago. We didn’t find any clean solution using the scrollView methods. Instead we found a workaround : see image (worths a thousand words :slight_smile:)


This solution is not perfect as you will see when you’ll try it, but it’s better than before.

If interested, I’ve made up a standard code (which should work roughly despite with some shifts on the positions):

    Sprite* overlay = Sprite::create(COM_WPIXEL); //white pixel image
    overlay ->setColor(Color3B(255,255,255));
    overlay ->setPosition(SCREEN_CENTER);
    overlay ->setScale(1500, 1100);
    interfaceOverlay->addChild(overlay, 98);
    
    Size scrollViewSize         = Size(1400,800);
    int distanceBetweenObjects  = 150;
    int numberObjects           = 3;
    
    auto scrollView =  ui::ScrollView::create();
    scrollView -> setPosition(Vec2(300,150));
    scrollView -> setDirection(ui::ScrollView::Direction::VERTICAL);
    scrollView -> setContentSize(scrollViewSize);
    
    
    for (int i =0; i < numberObjects; i++) {
    
        // Display of the information
        Sprite* object = Sprite::create(COM_WPIXEL);
        object -> setScale(1200, 100);
        object -> setColor(Color3B(52, 152, 219));
        object -> setPosition(724, i * distanceBetweenObjects + 700);
        scrollView->addChild(object);
        CCLOG("object X: %f, Y: %f", object->getPositionX(), object->getPositionY());
        
    }
    
    scrollView->setInnerContainerSize(Size(scrollViewSize.width, scrollViewSize.height + (numberObjects-1) * distanceBetweenObjects));

    scrollView->setBounceEnabled(true);
    interfaceOverlay->addChild(scrollView, 99);

Let me know if it’s interesting for you :slight_smile:

2 Likes

Hi @fitzfoufou
Thank you for sharing your solution.
I am interested of your solution. Could you share the standard code for me?
Many thanks for the help.

Hi @joelam500,
The standard code is the code in my first message. :slight_smile:
You should be able to use it yourself if you change a few positions or scales.
Let me know if you have other questions

Hi @fitzfoufou,

I already tried your code to set position, but the fixed position cannot be used for all cases.

For example, the number of button is less than 10 or larger than 10.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.