容器层的使用
GUI 控件我们大致可以分为两类,**普通控件** 和容器控件,普通控件指的是一些常用的控件,如 UIButton,UILabel,UiSlider 和 UITextField 等控件,而容器控件如 UILayout,UIScrollView,UIListView,UIPageView 等,这些容器控件都有一个特点,它可以作为容器,包含其它控件,虽然所有的控件都能够包含其它控件,但有些控件的职责非常单一,如按钮标签等,并不经常向其添加其它控件。以下详细介绍容器控件的使用方法。
UILayout (Panel)
Panel 作为最主要的容器层,前面我们说过,由 CocoStudio UI 编辑器所创建的 UI 是基于 Panel 来布局的,要想熟练的使用 UI 控件,了解 Panel 以及其属性也是重中之重,既然是容器,容器里面总得有些内容了,Panel 对应得控件名称为 UILayout。
Size widgetSize = m_pWidget->getSize@H_404_29@();
UILayout *background = dynamic_cast<UILayout*>@H_404_29@(m_pUiLayer->getWidgetByName@H_404_29@("background_Panel"@H_404_29@));
// Create the layout
UILayout* layout = UILayout::create@H_404_29@();
layout->setSize@H_404_29@(Size@H_404_29@(280@H_404_29@, 150@H_404_29@));
Size backgroundSize = background->getSize@H_404_29@();
layout->setPosition@H_404_29@(Point@H_404_29@((widgetSize@H_404_29@.width - backgroundSize@H_404_29@.width@H_404_29@) / 2 +
@H_404_29@(backgroundSize@H_404_29@.width - layout->getSize@H_404_29@().width@H_404_29@) / 2@H_404_29@,
@H_404_29@(widgetSize@H_404_29@.height - backgroundSize@H_404_29@.height@H_404_29@) / 2 +
@H_404_29@(backgroundSize@H_404_29@.height - layout->getSize@H_404_29@().height@H_404_29@) / 2@H_404_29@));
m_pUiLayer->addWidget@H_404_29@(layout@H_404_29@);
UIButton* button = UIButton::create@H_404_29@();
button->setTouchEnabled@H_404_29@(true@H_404_29@);
button->loadTextures@H_404_29@("cocosgui/animationbuttonnormal.png"@H_404_29@, "cocosgui/animationbuttonpressed.png"@H_404_29@,68); background:transparent">""@H_404_29@);
button->setPosition@H_404_29@(Point@H_404_29@(button->getSize@H_404_29@().width / layout->getSize@H_404_29@().height - button->getSize@H_404_29@().height / 2@H_404_29@));
layout->addChild@H_404_29@(button@H_404_29@);
UIButton* textButton = UIButton::create@H_404_29@();
textButton->setTouchEnabled@H_404_29@(true@H_404_29@);
textButton->loadTextures@H_404_29@("cocosgui/backtotopnormal.png"@H_404_29@,68); background:transparent">"cocosgui/backtotoppressed.png"@H_404_29@,68); background:transparent">""@H_404_29@);
textButton->setTitleText@H_404_29@("Text Button"@H_404_29@);
textButton->setPosition@H_404_29@(Point@H_404_29@(layout->getSize@H_404_29@().width / layout->getSize@H_404_29@().height / 2@H_404_29@));
layout->addChild@H_404_29@(textButton@H_404_29@);
UIButton* button_scale9 = UIButton::create@H_404_29@();
button_scale9->setTouchEnabled@H_404_29@(true@H_404_29@);
button_scale9->loadTextures@H_404_29@("cocosgui/button.png"@H_404_29@,68); background:transparent">"cocosgui/buttonHighlighted.png"@H_404_29@,68); background:transparent">""@H_404_29@);
button_scale9->setScale9Enabled@H_404_29@(true@H_404_29@);
button_scale9->setSize@H_404_29@(Size@H_404_29@(100@H_404_29@, button_scale9->getContentSize@H_404_29@().height@H_404_29@));
button_scale9->setPosition@H_404_29@(Point@H_404_29@(layout->getSize@H_404_29@().width - button_scale9->getSize@H_404_29@().width / button_scale9->getSize@H_404_29@().height / 2@H_404_29@));
layout->addChild@H_404_29@(button_scale9@H_404_29@);
如上面代码所示,我们创建了一个layout
控件,然后在其中添加了三个控件。m_pUiLayer
是当前场景的一个 UILayer ,前面我们介绍过,所有的 UI 控件,都是放在 UILayer 里面,UILayer 管理所有的控件,并添加到当前场景中去。显示效果如下:
我们设置了 layout 的 size 属性,也就是给它一个大小,但是并没有显示出来效果,默认是透明的,我们可以为这个层设置颜色:
layout->setBackGroundColorType@H_
404_29@(
LAYOUT_COLOR_SOLID@H_
404_29@);
layout->setBackGroundColor@H_
404_29@(
Color3B@H_
404_29@(
128@H_
404_29@,153); background:transparent">128@H_
404_29@));
除了设置纯色之外,还可以设计渐变颜色:
layout->setBackGroundColorType@H_
404_29@(
LAYOUT_COLOR_GRADIENT@H_
404_29@);
layout->setBackGroundColor@H_
404_29@(
Color3B@H_
404_29@(
64@H_
404_29@,153); background:transparent">64@H_
404_29@),
Color3B@H_
404_29@(
192@H_
404_29@,153); background:transparent">192@H_
404_29@));
当然,除了设置颜色之外,还可以设置我们想要的背景图片:
layout->setSize@H_
404_29@(
Size@H_
404_29@(
150@H_
404_29@));
layout->setClippingEnabled@H_
404_29@(
true@H_
404_29@);
layout->setBackGroundImage@H_
404_29@(
"cocosgui/Hello.png"@H_
404_29@);
如上图显示,我们设置了 size 并且设置了 背景图片,但是不要忘了调用setClippingEnabled
方法根据 size 进行裁剪,如果忘了调用,那么会向下面所显示的一样。
除了以上使用方式,还有其它玩法:
layout->setBackGroundImageScale9Enabled@H_
404_29@(
"cocosgui/green_edit.png"@H_
404_29@);
使用九宫格图片做为背景,注意启用此功能。
UILayout 显示颜色的模式有三种
LayoutBackGroundColorType |
说明 |
LAYOUT_COLOR_NONE |
透明,没有颜色显示 |
LAYOUT_COLOR_SOLID |
实体,可以设置颜色 |
LAYOUT_COLOR_GRADIENT
渐变颜色 |
UIPanel 控件的布局方案
UILayout 是作为布局之用,以上都只是修改背景图片,下面除了手动摆放坐标位置的绝对定位,还提供了哪些布局方案呢。
LayoutType
LAYOUT_ABSOLUTE
| 绝对布局 |
LAYOUT_LINEAR_VERTICAL
垂直平铺 |
LAYOUT_LINEAR_HORIZONTAL
横向平铺 |
LAYOUT_RELATIVE
相对布局 |
layout->setLayoutType@H_
404_29@(
LAYOUT_LINEAR_VERTICAL@H_
404_29@);
// 或者
layout->setLayoutType@H_
404_29@(
LAYOUT_LINEAR_HORIZONTAL@H_
404_29@);
// 或者
layout->setLayoutType@H_
404_29@(
LAYOUT_RELATIVE@H_
404_29@);
注意:除了绝对定位之外,如果设置了其它布局方案,那么 UIPanel 会忽略其内部控件本身设置的位置。而此时可以使用提供的UILayoutParameter
来设置位置关系,根据布局方案提供了几种布局参数,UILinearLayoutParameter
和UIRelativeLayoutParameter
。下面介绍如何实用布局参数来配合布局设计界面显示效果。
// .... 省略控件创建
代码,同前文控件一样
UILinearLayoutParameter* lp1 = UILinearLayoutParameter::create@H_
404_29@();
lp1->setGravity@H_
404_29@(
LINEAR_GRAVITY_CENTER_HORIZONTAL@H_
404_29@);
lp1->setMargin@H_
404_29@(
UIMargin@H_
404_29@(
0@H_
404_29@,153); background:transparent">10@H_
404_29@,153); background:transparent">10@H_
404_29@));
UILinearLayoutParameter* lp2 = UILinearLayoutParameter::create@H_
404_29@();
lp2->setGravity@H_
404_29@(
LINEAR_GRAVITY_CENTER_HORIZONTAL@H_
404_29@);
lp2->setMargin@H_
404_29@(
UIMargin@H_
404_29@(
20@H_
404_29@,153); background:transparent">5@H_
404_29@));
UILinearLayoutParameter* lp3 = UILinearLayoutParameter::create@H_
404_29@();
lp3->setGravity@H_
404_29@(
LINEAR_GRAVITY_CENTER_HORIZONTAL@H_
404_29@);
lp3->setMargin@H_
404_29@(
UIMargin@H_
404_29@(
10@H_
404_29@));
button->setLayoutParameter@H_
404_29@(
lp1@H_
404_29@);
textButton->setLayoutParameter@H_
404_29@(
lp2@H_
404_29@);
button_scale9->setLayoutParameter@H_
404_29@(
lp3@H_
404_29@);
显示效果如下:
我们看到,分别创建了三个布局参数UILinearLayoutParameter
,设置了Gravity
和Margin
参数,然后给三个 UIPanel 的内部控件分别设置其布局参数值,已达到如上效果。
这里使用的方案是垂直平铺,而每个布局参数设置的Gravity
值为LINEAR_GRAVITY_CENTER_HORIZONTAL
,也就是说水平剧中显示,而 Margin 则标示控件四周边缘的间距,注意以上的lp2
的值为UIMargin(20,20,5)
,其代表含义,距离左、上、右、下的间距。左值为 20,可以看见textButton
相对中间位置向右便宜少数。这是垂直布局,而水平布局除了方向不一,基本使用方式同垂直布局同样。两者也都叫线性布局,使用同样的线性布局参数。下面再看看相对布局:
layout->setLayoutType@H_
404_29@(
LAYOUT_RELATIVE@H_
404_29@);
// 此处省略控件的创建步骤 ...
UIRelativeLayoutParameter* rp1 = UIRelativeLayoutParameter::create@H_
404_29@();
rp1->setAlign@H_
404_29@(
RELATIVE_ALIGN_PARENT_TOP_RIGHT@H_
404_29@);
UIRelativeLayoutParameter* rp2 = UIRelativeLayoutParameter::create@H_
404_29@();
rp2->setAlign@H_
404_29@(
RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL@H_
404_29@);
UIRelativeLayoutParameter* rp3 = UIRelativeLayoutParameter::create@H_
404_29@();
rp3->setAlign@H_
404_29@(
RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM@H_
404_29@);
button->setLayoutParameter@H_
404_29@(
rp1@H_
404_29@);
textButton->setLayoutParameter@H_
404_29@(
rp2@H_
404_29@);
button_scale9->setLayoutParameter@H_
404_29@(
rp3@H_
404_29@);
这里创建了三个布局属性,设置了不同的 "停靠" 参数Align
。
除了布局容器,我们常用的还有滚动层容器,它可以扩大我们的显示控件,当内容元素很多时,尤为有用。可以设置为两个方向,横向或者是竖向。
UIScrollView* scrollView = UIScrollView::create@H_
404_29@();
scrollView->setTouchEnabled@H_
404_29@(
true@H_
404_29@);
scrollView->setSize@H_
404_29@(
Size@H_
404_29@(
150@H_
404_29@));
Size backgroundSize = background->getContentSize@H_
404_29@();
scrollView->setPosition@H_
404_29@(
Point@H_
404_29@((
widgetSize@H_
404_29@.
width - backgroundSize@H_
404_29@.
width@H_
404_29@)
/ 2 +
@H_
404_29@(
backgroundSize@H_
404_29@.
width - scrollView->getSize@H_
404_29@().
width@H_
404_29@)
/ 404_29@(widgetSize@H_
404_29@.
height - backgroundSize@H_
404_29@.
height@H_
404_29@)
/ 2 +
@H_
404_29@(
backgroundSize@H_
404_29@.
height - scrollView->getSize@H_
404_29@().
height@H_
404_29@)
/ 2@H_
404_29@));
m_pUiLayer->addWidget@H_
404_29@(
scrollView@H_
404_29@);
UIImageView* imageView = UIImageView::create@H_
404_29@();
imageView->loadTexture@H_
404_29@(
"cocosgui/ccicon.png"@H_
404_29@);
float innerWidth = scrollView->getSize@H_
404_29@().
width@H_
404_29@;
float innerHeight = scrollView->getSize@H_
404_29@().
height + imageView->getSize@H_
404_29@().
height@H_
404_29@;
scrollView->setInnerContainerSize@H_
404_29@(
Size@H_
404_29@(
innerWidth@H_
404_29@,
innerHeight@H_
404_29@));
imageView->setPosition@H_
404_29@(
Point@H_
404_29@(
innerWidth / imageView->getSize@H_
404_29@().
height / 2@H_
404_29@));
scrollView->addChild@H_
404_29@(
imageView@H_
404_29@);
// 为 scrollview 添加其它控件,省略
请看如图效果,这里创建了一个 ScrollView 控件,并且添加了一些内部元素,以完成布局,控件内容超出显示区域,我们可以通过上下拖动,来显示上下未未显示的不分。
注意: imageView 设置的位置在 scrollview 之外,可以通过 scrollview 的 setInnerContainerSize 方法设置包含内容的区域大小,在拖动的过程中,边界检查。
如果是设置横向的拖动效果,我们只需要设置 InnerContainerSize 的 宽度大于控件的大小,高度相同,就能实现横向的拖动效果。
UIListView
ListView 继承自 ScrollView,所以 ScrollView 里面有的功能,特性,在 ListView 中也都能体现出来。那么 ListView 相比较 ScrollView 多了些什么呢?还是先从使用方法上开始:
UIListView* lv = UIListView::create@H_
404_29@();
UIButton* model = UIButton::create@H_
404_29@();
model->loadTextures@H_
404_29@(
""@H_
404_29@);
lv->setItemModel@H_
404_29@(
model@H_
404_29@);
for @H_
404_29@(
int i=0@H_
404_29@;
i<20@H_
404_29@;
i++@H_
404_29@)
@H_
404_29@{
lv->pushBackDefaultItem@H_
404_29@();
@H_
404_29@}
lv->setItemsMargin@H_
404_29@(
10@H_
404_29@);
lv->setGravity@H_
404_29@(
LISTVIEW_GRAVITY_CENTER_HORIZONTAL@H_
404_29@);
lv->setSize@H_
404_29@(
Size@H_
404_29@(
100@H_
404_29@));
lv->setBackGroundColorType@H_
404_29@(
LAYOUT_COLOR_SOLID@H_
404_29@);
lv->setBackGroundColor@H_
404_29@(
Color3B::GREEN@H_
404_29@);
lv->setPosition@H_
404_29@(
Point@H_
404_29@(
100@H_
404_29@));
m_pUiLayer->addWidget@H_
404_29@(
lv@H_
404_29@);
如图,但不能很好的看到效果,这里是类似 ScrollView 的实现,可以实现拖动,并且有二十个按钮在这其中。先说说普通的属性,通过ItemsMargin
设置每个元素的间距, 通过Gravity
设置布局方案,这里是横向剧中显示。
lv->setItemModel(model)
为 ListView 设置了默认的项 (Default Item),然后通过一个 for 循环,添加了 20 次此默认的项,注意这 20 次并不是说, model 被添加了 20 次,二十在每次添加的时候都对 model 做了一个 克隆,它们拥有相同的属性,但却不是同一个对象。
除了使用pushBackDefaultItem()
为 ListView 添加项之外,我们还可以通过以下方法添加:
方法
pushBackDefaultItem()
| 添加一个默认项 |
insertDefaultItem(int index)
插入一个默认项,有序的 |
pushBackCustomItem(UIWidget* item)
添加一个新项 |
insertCustomItem(UIWidget* item,int index)
插入一个新项 |
以上是提供的一些添加项的方法,除了以上还有一些删除的方法,获取的方法,以便我们能够灵活的操作其中的每个元素:
removeItem(int index)
移除一个项 |
removeLastItem()
移除最后一个项 |
getItem(unsigned int index)
根据索引获取一个项 |
getItems()
获取所有项,返回 Array 集合 |
getIndex(UIWidget *item)
获取一个项的索引 |
UIPageView
除了可以滚动显示的 ScrollView , 根据项来显示列表的控件之外,还有可以根据 页 来显示 PageView。 PageVew 可以让我们整页整页的显示内容,并且可以做自动对齐,什么是自动对齐,就像你的书翻页,只翻了一半,它回自动帮你翻过去一样。
UIPageView* pageView = UIPageView::create@H_
404_29@();
pageView->setTouchEnabled@H_
404_29@(
true@H_
404_29@);
pageView->setSize@H_
404_29@(
Size@H_
404_29@(
240@H_
404_29@,153); background:transparent">130@H_
404_29@));
Size backgroundSize = background->getContentSize@H_
404_29@();
pageView->setPosition@H_
404_29@(
Point@H_
404_29@((
widgetSize@H_
404_29@.
width - backgroundSize@H_
404_29@.
width@H_
404_29@)
/ 2 +
@H_
404_29@(
backgroundSize@H_
404_29@.
width - pageView->getSize@H_
404_29@().
width@H_
404_29@)
/ 404_29@(widgetSize@H_
404_29@.
height - backgroundSize@H_
404_29@.
height@H_
404_29@)
/ 2 +
@H_
404_29@(
backgroundSize@H_
404_29@.
height - pageView->getSize@H_
404_29@().
height@H_
404_29@)
/ 2@H_
404_29@));
for @H_
404_29@(
int i = 0@H_
404_29@;
i < 3@H_
404_29@;
++i@H_
404_29@)
@H_
404_29@{
UILayout* layout = UILayout::create@H_
404_29@();
layout->setSize@H_
404_29@(
Size@H_
404_29@(
130@H_
404_29@));
UIImageView* imageView = UIImageView::create@H_
404_29@();
imageView->setTouchEnabled@H_
404_29@(
true@H_
404_29@);
imageView->setScale9Enabled@H_
404_29@(
true@H_
404_29@);
imageView->loadTexture@H_
404_29@(
"cocosgui/scrollviewbg.png"@H_
404_29@);
imageView->setSize@H_
404_29@(
Size@H_
404_29@(
130@H_
404_29@));
imageView->setPosition@H_
404_29@(
Point@H_
404_29@(
layout->getSize@H_
404_29@().
width / 2@H_
404_29@));
layout->addChild@H_
404_29@(
imageView@H_
404_29@);
UILabel* label = UILabel::create@H_
404_29@();
label->setText@H_
404_29@(
CCString::createWithFormat@H_
404_29@(
"page %d"@H_
404_29@, @H_
404_29@(
i + 1@H_
404_29@))
->getCString@H_
404_29@());
label->setFontName@H_
404_29@(
font_UIPageViewTest@H_
404_29@);
label->setFontSize@H_
404_29@(
30@H_
404_29@);
label->setColor@H_
404_29@(
Color3B@H_
404_29@(
192@H_
404_29@));
label->setPosition@H_
404_29@(
Point@H_
404_29@(
layout->getSize@H_
404_29@().
width / 2@H_
404_29@));
layout->addChild@H_
404_29@(
label@H_
404_29@);
pageView->addPage@H_
404_29@(
layout@H_
404_29@);
@H_
404_29@}
pageView->addEventListenerPageView@H_
404_29@(
this@H_
404_29@,
pagevieweventselector@H_
404_29@(
UIPageViewTest::pageViewEvent@H_
404_29@));
m_pUiLayer->addWidget@H_
404_29@(
pageView@H_
404_29@);
如图显示,创建了一个 PageView 对象 pageView,设置大小为 "Size(240,130)",这也就是它的显示区域大小了。我们使用一个 for 循环,添加了三个同样的元素 UILayout ,每个 UILayout 的大小也都是Size(240,130)
,所以 PageView 一次正好能够显示一个项的内容,也就是 "页"。至于每个页的 UILayout 里面装着什么,那就是根据自己的需要而定了。然后使用pageView->addPage(layout)
添加一个页,需要注意的是,这里所添加的必须是UILayout
类型对象或者其派生类对象。
PageView 虽然实现了滑动,滚动的效果,但它并不是继承自 ScrollView 的,而是直接继承自 UILayout 的,那怎么实现滚动的呢,它集成并且实现了UIScrollInterface
类型,这赋予了它可以滚动的属性。ScrollView 也是同样。
各个控件组成了丰富的 GUI 界面,而容器层则是其骨架,通过它的布局,来达到我们想要的效果。从 Panel 到 ScrollView ,Listview 和 PageView ,根据实际的需要灵活的组织可以让我们的界面显示的更为友好。