Can I have container widgets inside a ListView?

Hello!

When I try to add ui::Layout items to ui::ListView, it (looks like it) absorbs all events and the ListView won’t scroll on touch. When I add simple widgets like ui::ImageView, it works as expected.

So, is it possible for a ListView to contain complex items and what’s the way to do so?

You may be able to use setPropagateTouchEvents(false) to get what you want. Otherwise you may need to subclass your internal layouts (that steal touch events) and override the touch behavior. I know there are some scrollview inside scrollview discussions on the forum.

Thanks for your reply. I tried that, but it didn’t work. :frowning:
I’m searching for examples of subclassing the ui::Widget class for ListView items, but haven’t found any so far. Can someone please give me an example?

Can you share more about your setup you are trying to achieve? What Widgets are you trying to put inside a ListView that doesn’t work?

You may have to attach touch event listeners to the ListView and specific children, or subclass it and handle all the touch propagation yourself.

We have a ListView with Layout children and each Layout has an ImageView as a child. We handle the touch events ourselves to both “highlight” the correct ImageView as well as “un-highlight” the ImageView if a touch was cancelled or the touch wasn’t a tap.

// selectedWidget is class member of type ui::Widget
ui::ListView::ccListViewCallback func = [this](cocos2d::Ref* senderRef, cocos2d::ui::ListView::EventType e) {
        dlog("enter listview event");
        auto lv = dynamic_cast<ListView*>(senderRef);
        if(lv) {
            this->selectedIndex = int(lv->getCurSelectedIndex());
            dlog("cur selected index = " PRINTF_ZD "", selectedIndex);

            if(e == ListView::EventType::ON_SELECTED_ITEM_END)
            {
                if(selectedWidget) {
                    selectedWidget->setColor(Color3B::WHITE);
                    selectedWidget = nullptr;
                }

                log("list view selection end");
                auto widget = lv->getCurrentFocusedWidget();
                if(!widget) widget = lv->getItem(selectedIndex);

                if(widget) {
                    widget->setCascadeColorEnabled(true);
                    widget->setColor(Color3B::WHITE);
                    int index = (int)lv->getIndex(widget) - 1;
                    log("index = %d", index);
                    // action
                }

                log("cur selected index = " PRINTF_ZD "", lv->getCurSelectedIndex());
            }
            else if(e == ListView::EventType::ON_SELECTED_ITEM_START)
            {
                log("list view selection start");
                auto widget = lv->getCurrentFocusedWidget();
                if(! widget) widget = lv->getItem(selectedIndex);

                if(widget) {
                    widget->setCascadeColorEnabled(true);
                    widget->setColor(Color3B(200,200,200));

                    auto index = lv->getIndex(widget);
                    CC_UNUSED_PARAM(index);
                    dlog("index = " PRINTF_ZD "", index);
                    
                    selectedWidget = widget;
                }
            }
        }
    };
    listview->addEventListener(func);

Same problem, is there any idea ?
The solution above might not work with me ( or I dont know clearly )
I wanna add a ui::Layout in to the ui::ListView, well, it added as expected, but doesn’t handle any event eventhough I’ve added it own touch ( and mouse click ) listener
Like this:

auto layout = ui::Layout::create();
	layout->setContentSize(Size(500, 100));
	layout->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
	layout->setBackGroundColor(Color3B::GREEN);
	layout->addTouchEventListener([](Ref* pSender,ui::Widget::TouchEventType type)
	{
		if (type == ui::Widget::TouchEventType::BEGAN)
			log("Layout has just been clicked");
	});

When debugging, there is nothing shown on the console, but work if I added a normal UIButton with just this code

auto tempButton = ui::Button::create("Graphics/GUI/Selection_Normal.png",
		"Graphics/GUI/Selection_Select.png");

Ofcourse addChild after those lines.
Well, as you see, the layout has it own listener but didnt work. Why was that ? And how to fix it ?
Please help

I have the same difficulty to work with this on v3.7 and i think cocos2d-x team should have more detailed samples on how to use a combination of ListView/ScrollView and Containers since I see many threads related to ListView issues.

After searching, i find that the below thread is very useful.

http://discuss.cocos2d-x.org/t/erro-add-a-controlswitch-to-cell-of-listview-items-on-other-cell-not-display/18985

Extracting the code in the for loop of the above thread works for me.