美文网首页
7-ListView添加子项后跳到原来的位置

7-ListView添加子项后跳到原来的位置

作者: porridgechen890 | 来源:发表于2019-12-22 17:04 被阅读0次

问题由来

一个排行榜列表,开始只加载10条数据。如果用户滑到底了,向服务器请求数据,收到数据后,往列表里加10条数据(是追加,不是清空列表再加载20条数据)。但问题是每次加入子项后,列表框跳到顶部去了。

解决方法

ListView里有这么个方法。
void jumpToItem(ssize_t itemIndex, const Vec2& positionRatioInView, const Vec2& itemAnchorPoint);
第一个参数是item的序号,加进ListView的item是从0开始递增的。
第二个参数是相对于列表框大小的比率。比方说,Vec2(0.5,0.5)表示列表框的正中心。
第三个参数是item的锚点。
那么这个函数的作用就是,把序号为itemIndex的子项,以itemAnchorPoint为锚点,放到以列表框左下角为原点的坐标系里的点(列表框宽 乘 positionRatioInView.x, 列表框高 乘 positionRatioInView.y)那里去。

代码

bool HelloWorld::init()
{
    if ( !cocos2d::Scene::init() )
    {
        return false;
    }
    
    auto visibleSize = cocos2d::Director::getInstance()->getVisibleSize();
    auto origin = cocos2d::Director::getInstance()->getVisibleOrigin();

    auto lsv = cocos2d::ui::ListView::create();
    lsv->setContentSize(cocos2d::Size(300, 300));
    lsv->setAnchorPoint(cocos2d::Vec2(0.5, 0.5));
    lsv->setPosition(origin + cocos2d::Vec2(visibleSize / 2));
    lsv->setBackGroundColor(cocos2d::Color3B::GRAY);
    lsv->setBackGroundColorType(cocos2d::ui::Layout::BackGroundColorType::SOLID);
    lsv->setDirection(cocos2d::ui::ScrollView::Direction::VERTICAL);
    lsv->setGravity(cocos2d::ui::ListView::Gravity::CENTER_HORIZONTAL);
    lsv->setBounceEnabled(true);
    lsv->setScrollBarAutoHideEnabled(false);
    lsv->setItemsMargin(10);
    lsv->addEventListener((cocos2d::ui::ScrollView::ccScrollViewCallback)
        CC_CALLBACK_2(HelloWorld::onEventScrollView, this));
    addChild(lsv, 2, "lsv");

    m_page = 1;//表示当前请求的是第几页数据
    push10ItemsIntoListView();//假设第一页收到响应了,这不重要好吧

    return true;
}
void HelloWorld::push10ItemsIntoListView()
{
    cocos2d::log("push items into listview. current page = %d", m_page);
    auto lsv = dynamic_cast<cocos2d::ui::ListView*>(this->getChildByName("lsv"));
    for (int i = 0; i < 10; i++)
    {
        auto panel = cocos2d::ui::Layout::create();
        panel->setContentSize(cocos2d::Size(250, 40));
        panel->setBackGroundColor(cocos2d::Color3B::ORANGE);
        panel->setBackGroundColorType(cocos2d::ui::Layout::BackGroundColorType::SOLID);
        lsv->pushBackCustomItem(panel);
        int n = (m_page - 1) * 10 + i;
        auto txt = cocos2d::ui::Text::create(cocos2d::StringUtils::format("%d", n), "fonts/arial.ttf", 40);
        txt->setPosition(cocos2d::Vec2(panel->getContentSize() / 2));
        txt->setName("txt1");
        panel->addChild(txt);
    }
    if (m_page > 1)
    {
        cocos2d::log("listview jump to item %ld", m_bottomWidgetIndex);
        lsv->jumpToItem(m_bottomWidgetIndex, cocos2d::Vec2(0.5, 0), cocos2d::Vec2(0.5, 0));
    }
}
void HelloWorld::onEventScrollView(cocos2d::Ref* pSender, cocos2d::ui::ScrollView::EventType type)
{
    auto lsv = dynamic_cast<cocos2d::ui::ListView*>(pSender);
    switch (type)
    {
    case cocos2d::ui::ScrollView::EventType::AUTOSCROLL_ENDED:
        {
            auto wgt_bottom = lsv->getBottommostItemInCurrentView();
            m_bottomWidgetIndex = lsv->getIndex(wgt_bottom);
            cocos2d::log("0 autoscroll ended. bottom widget's index = %ld", m_bottomWidgetIndex);
            if (m_bottomWidgetIndex == m_page * 10 - 1)
            {
                cocos2d::log("1 listview reached bottom");

                m_page++;
                httpRequest(m_page);
            }
        }
        break;
    default:
        break;
    }
}
void HelloWorld::httpRequest(int page)
{
    cocos2d::log("2 send request");
    //假设这里的请求参数里需要用到page,代表请求第几页数据
    const char* postData = "visitor=cocos2d&TestSuite=Extensions Test/NetworkTest";
    auto request = new (std::nothrow) cocos2d::network::HttpRequest();
    request->setUrl("http://httpbin.org/post");
    request->setRequestType(cocos2d::network::HttpRequest::Type::POST);
    request->setResponseCallback(CC_CALLBACK_2(HelloWorld::onHttpRequestCompleted, this));
    request->setRequestData(postData, strlen(postData));
    cocos2d::network::HttpClient::getInstance()->send(request);
    request->release();
}
void HelloWorld::onHttpRequestCompleted(cocos2d::network::HttpClient* client, cocos2d::network::HttpResponse* response)
{
    cocos2d::log("3 recv response");
    if (!response)
    {
        return;
    }
    if (!response->isSucceed())
    {
        cocos2d::log("code=%ld buffer=%s", response->getResponseCode(), response->getErrorBuffer());
        return;
    }
    std::vector<char>* buffer = response->getResponseData();
    //假设这里返回的是10条需要加入列表框的数据
    auto lsv = dynamic_cast<cocos2d::ui::ListView*>(this->getChildByName("lsv"));
    push10ItemsIntoListView();
}

方法的不足

jump到某个item,还是会闪一下,用户体验不好。

参考

cocos2dx使用listView->scrollToItem在滚动的中途触发滚动会乱套
ListView not aligning magnetically like expected with scrolltoitem

a.gif

相关文章

网友评论

      本文标题:7-ListView添加子项后跳到原来的位置

      本文链接:https://www.haomeiwen.com/subject/gemonctx.html