Uilistview is often used in the UI interface in real-world projects, and most of the controls are added directly to the Cocostudio. But in use found some pits and lack of function, and then looked at the underlying logic, found a little change to the bottom to meet the demand, so the following for the needs to analyze the bottom of the uilistview, while making some changes.
Requirements: Dynamically adjust the size of the ListView itself according to the contents of the linked list
First, we need to know how we insert and remove an item from a linked list, and how the ListView will handle it:
123456789101112131415 |
void ListView::pushBackDefaultItem()
{
if (!_model)
{
return
;
}
/* 克隆一份模板,并添加到项的数组里 */
Widget* newItem = _model->clone();
_items->addObject(newItem);
/* 根据listView的基础设置来调整新加项的布局关系 */
remedyLayoutParameter(newItem);
addChild(newItem);
/* 重点:打开刷新开关 */
_refreshViewDirty =
true
;
}
|
Here the last sentence is the focus, only the refresh will really calculate the new display, before the change is really effective, so let us add an item, the current frame does not immediately refresh, if this time to get the size, only and before the same, and did not change, then we have to know, switch _ When did the refreshviewdirty come into play, as follows:
?
12345678910 |
void ListView::sortAllChildren()
{
ScrollView::sortAllChildren();
if (_refreshViewDirty)
{
/* 刷新 */
refreshView();
_refreshViewDirty =
false
;
}
}
|
?
1234567891011 |
void ListView::refreshView()
{
ccArray* arrayItems = getItems()->data;
int length = arrayItems->num;
for (
int i=
0
; i<length; item=
"static_cast<Widget*"
>(arrayItems->arr[i]);
item->setZOrder(i);
remedyLayoutParameter(item);
}
/* 更新内容大小 */
updateInnerContainerSize();
}</length;>
|
You can see that the most critical change in the size of the function updateinnercontainersize ():
Define a variable to hold the actual size, because the ListView itself calculates the size of the result is not based on the content, but the size of the initial user set, then the real size will be abandoned, so we have to save her:
?
1 |
CCSize _actualInnerSize; |
?
1234567891011121314151617181920212223242526 |
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); This function is defined in the parent class:
12345678910111213141516171819202122232425262728 |
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
));
}
|
In the Updateinnercontainersize function we save the actual content size, we need to write a get function to obtain:
?
123456 |
CCSize ListView::getActualInnerSize() { /* 重点:立即(当前帧)执行刷新,更新大小 */ refreshView(); return _actualInnerSize; } |
Final implementation requirements: Listview->setsize (Getactualinnersize ())
The above is the Uilistview control added in Cocostudio, and if it is created manually, there are three points to note:
To be able to scroll, implement two conditions
①:settouchenable (True)
②: Be sure to put Uilistview into Uilayer, only Uilayer will listen to the UI series touch, Cclayer can not
So need to create a uilayer* layer;layer->addwidget (list),//Must be addwidget, the expression is added as a pendant, addchild can not, and finally addchild (layer);
③: When you add a control to a list, the list is automatically placed, where the position is not managed manually (and the position is usually incorrect, the center point is in the upper-left corner, we cannot change it, do the relative offset, etc.); but sometimes we can only add the middle layer, such as uilayout, to adjust the position. and uilayout to note that it is equivalent to a layer, the coordinate calculation and the same layer.
Cocos2d-x to get the actual content size of Uilistview