美文网首页
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