• cocos2d-x改底层之获取UIListView的实际内容大小


    实际项目中UI界面中常常会用到UIListView。大多会在CocoStudio中直接加入这个控件。

    可是在使用中发现了一些坑和功能缺乏,然后就看了一下底层的逻辑,发现略微改一下底层就能够满足需求,所以以下就针对需求来分析UIListView的底层。同一时候做一些修改。


    需求:依据链表中的内容来动态调整listView本身的大小

    首先,我们要知道。我们插入和移除链表中的一项,listView本身会怎样处理:

    void ListView::pushBackDefaultItem()
    {
        if (!_model)
        {
            return;
        }
        /* 克隆一份模板,并加入到项的数组里 */
        Widget* newItem = _model->clone();
        _items->addObject(newItem);
        /* 依据listView的基础设置来调整新加项的布局关系 */
        remedyLayoutParameter(newItem);
        addChild(newItem);
        /* 重点:打开刷新开关 */
        _refreshViewDirty = true;
    }

    这里最后一句才是重点。仅仅有刷新了才会真正计算新的显示,之前的修改才真正生效。所以放我们加入一项的时候,当前帧事实上并没有马上刷新。假设这时候获取大小。仅仅会和之前的一样,并没有改变,那么我们要知道,开关_refreshViewDirty是在什么时候起作用了呢,例如以下:

    void ListView::sortAllChildren()
    {
        ScrollView::sortAllChildren();
        if (_refreshViewDirty)
        {
            /* 刷新 */
            refreshView();
            _refreshViewDirty = false;
        }
    }
    void ListView::refreshView()
    {
        ccArray* arrayItems = getItems()->data;
        int length = arrayItems->num;
        for (int i=0; i<length; i++)
        {
            Widget* item = static_cast<Widget*>(arrayItems->arr[i]);
            item->setZOrder(i);
            remedyLayoutParameter(item);
        }
        /* 更新内容大小 */
        updateInnerContainerSize();
    }

    能够看到。最关键的改变大小的函数updateInnerContainerSize():

    定义一个变量用来保存真实大小,原因是listView本身计算大小的结果并非以内容为准,而是以最初用户设置的大小,那么真实的大小会被遗弃,所以我们要保存住她:

    CCSize _actualInnerSize;
    void ListView::updateInnerContainerSize()
    {
        switch (_direction)
        {
            case SCROLLVIEW_DIR_VERTICAL:
            {
                /*...*/
                
                /* 保存真实大小 */
                _actualInnerSize = CCSize(finalWidth, finalHeight);
                setInnerContainerSize(_actualInnerSize);
                break;
            }
            case SCROLLVIEW_DIR_HORIZONTAL:
            {
                /*...*/
                
                /* 保存真实大小 */
                _actualInnerSize = CCSize(finalWidth, finalHeight);
                setInnerContainerSize(_actualInnerSize);
                break;
            }
            default:
                break;
        }
    }


    setInnerContainerSize(_actualInnerSize);这个函数是在父类定义的:

    void ScrollView::setInnerContainerSize(const CCSize &size)
    {
        /* 获取用户设置的大小(没设置就是默认的) */
        float innerSizeWidth = _size.width;
        float innerSizeHeight = _size.height;
        /* 获取原始大小 */
        CCSize originalInnerSize = _innerContainer->getSize();
        /* 更新后的新的内容大小与设置的大小作比較 */
        if (size.width < _size.width)
        {
            /* 假设新的内容大小比设置的要小,输出提示,并以设置的大小为准,大小不改变 */
            CCLOG("Inner width <= scrollview width, it will be force sized!");
        }
        else
        {
            /* 假设新的内容大小比设置的要大。则以新内容大小为准 */
            innerSizeWidth = size.width;
        }
        if (size.height < _size.height)
        {
            CCLOG("Inner height <= scrollview height, it will be force sized!");
        }
        else
        {
            innerSizeHeight = size.height;
        }
        _innerContainer->setSize(CCSize(innerSizeWidth+5, innerSizeHeight+10));
    }

    在updateInnerContainerSize函数中我们以保存了实际内容大小,须要写一个get函数来获取:

    CCSize ListView::getActualInnerSize()
    {
        /* 重点:马上(当前帧)运行刷新。更新大小 */
    	refreshView();
        return _actualInnerSize;
    }


    最后实现需求:listView->setSize(getActualInnerSize())


    上面是在CocoStudio中加入的UIListView控件,假设是手动创建的话有三点注意:

    为了可以滚动,要实现两个条件

    ①:setTouchEnable(true)

    ②:一定要将UIListView 放入到UILayer中,仅仅有UILayer才会监听UI系列触摸。CCLayer不能够

    所以须要创建一个UILayer* layer;layer->addWidget(list);//一定是addWidget。表示以挂件形式加入,addChild不能够。最后再addChild(layer)。

    ③:向列表中加入控件时,列表会自己主动排好位置,此时位置是不受手动管理的(并且位置通常不正确,中心点在左上角,我们无法改变,做相对偏移等);但有时候我们为了调整位置,仅仅能加入中间层。如UILayout。而UILayout要注意的是,它相当于一个层,坐标计算和层一样。



  • 相关阅读:
    奶酪(NOIP2017 Day2 T1)
    图的遍历(某谷P3916)
    20154331 EXP9web安全基础实践
    20154331 EXP8 web基础
    20154331EXP7 网络欺诈
    20154331 Exp6 信息搜集与漏洞扫描
    Exp5 MSF基础应用
    Exp4 恶意代码分析
    Exp3 免杀原理与实践
    20154331黄芮EXP2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7200678.html
Copyright © 2020-2023  润新知