Developers Manual > Cocos2d-x > Modules > New UI > Widget

Introduction to Regular Widgets

We introduced the basic usage of Button before to control a display content of Text. ImageView is easy to use, and GUI also provides us some other useful widgets such as CheckBox and Slider etc.

Text Button

In C++:

1
2
3
4
5
6
7
    Button* textButton = Button::create();
    textButton->setTouchEnabled(true);
    textButton->loadTextures("cocosgui/backtotopnormal.png", "cocosgui/backtotoppressed.png", "");
    textButton->setTitleText("Text Button");
    textButton->setPosition(Point(widgetSize.width / 2.0f, widgetSize.height / 2.0f));
    textButton->addTouchEventListener(this, toucheventselector(UITextButtonTest::touchEvent));        
    this->addChild(textButton);

In Lua:

1
2
3
4
5
6
7
    local textButton = ccui.Button:create()
    textButton:setTouchEnabled(true)
    textButton:loadTextures("cocosui/backtotopnormal.png", "cocosui/backtotoppressed.png", "")
    textButton:setTitleText("Text Button")
    textButton:setPosition(cc.p(widgetSize.width / 2.0, widgetSize.height / 2.0))
    textButton:addTouchEventListener(touchEvent)        
    self._uiLayer:addChild(textButton)

uitextbutton

As button, it has to support touch event. Then call loadTextures method to load image. Notice the third parameter is the display image when button is disabled. Let's focus on the fourth parameter, checking out following method's prototype:

void loadTextures(const char* normal,const char* selected,const char* disabled,TextureResType texType = TextureResType::LOCAL);

The last parameter is image type, default as TextureResType::LOCAL, which means using normal image. On the other hand, the other TextureResType::PLIST is using the resource from plist, and this decide to use Sprite or SpriteFrame creating displaying sprite. We can also use squared picture, remember setting Size.

In C++:

1
2
3
4
5
6
7
8
9
    UIButton* textButton = UIButton::create();
    textButton->setTouchEnabled(true);
    textButton->setScale9Enabled(true);
    textButton->loadTextures("cocosgui/button.png", "cocosgui/buttonHighlighted.png", "");
    textButton->setSize(Size(180, textButton->getContentSize().height * 1.5f));
    textButton->setTitleText("Text Button scale9 render");
    textButton->setPosition(Point(widgetSize.width / 2.0f, widgetSize.height / 2.0f));
    textButton->addTouchEventListener(this, toucheventselector(UITextButtonTest::touchEvent));        
    m_pUiLayer->addWidget(textButton);

In Lua:

1
2
3
4
5
6
7
8
9
  local textButton = ccui.Button:create()
    textButton:setTouchEnabled(true)
    textButton:setScale9Enabled(true)
    textButton:loadTextures("cocosui/button.png", "cocosui/buttonHighlighted.png", "")
    textButton:setContentSize(cc.size(180, textButton:getVirtualRendererSize().height * 1.5))
    textButton:setTitleText("Text Button scale9 render")
    textButton:setPosition(cc.p(widgetSize.width / 2.0, widgetSize.height / 2.0))
    textButton:addTouchEventListener(touchEvent)        
    self._uiLayer:addChild(textButton)

uitextbutton9

CheckBox

We also see a widget in web page-checkbox, it allows you choose more than one item.

In C++:

1
2
3
4
5
6
7
8
9
10
    CheckBox* checkBox = CheckBox::create();
    checkBox->setTouchEnabled(true);
    checkBox->loadTextures("cocosgui/check_box_normal.png",
                           "cocosgui/check_box_normal_press.png",
                           "cocosgui/check_box_active.png",
                           "cocosgui/check_box_normal_disable.png",
                           "cocosgui/check_box_active_disable.png");
    checkBox->setPosition(Point(widgetSize.width / 2.0f, widgetSize.height / 2.0f));
    checkBox->addEventListener(CC_CALLBACK_2(UICheckBoxTest::selectedEvent),this);
    this->addWidget(checkBox);

In Lua:

1
2
3
4
5
6
7
8
9
10
11
12
 local checkBox = ccui.CheckBox:create()
    checkBox:setTouchEnabled(true)
    checkBox:loadTextures("cocosui/check_box_normal.png",
                               "cocosui/check_box_normal_press.png",
                               "cocosui/check_box_active.png",
                               "cocosui/check_box_normal_disable.png",
                               "cocosui/check_box_active_disable.png")
    checkBox:setPosition(cc.p(widgetSize.width / 2.0, widgetSize.height / 2.0))

    checkBox:addEventListener(selectedEvent)  

    self._uiLayer:addChild(checkBox)

uicheckbox

There are not too much properties in here, but many images loaded-two status images, two disabled status images and pressed image. These five images build a checkbox, setting callback method by addEventListener:

In C++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void UICheckBoxTest::selectedEvent(Ref* pSender,CheckBox::EventType type)
{
    switch (type)
    {
        case CheckBox::EventType::SELECTED:
            _displayValueLabel->setString(String::createWithFormat("Selected")->getCString());
            break;

        case CheckBox::EventType::UNSELECTED:
            _displayValueLabel->setString(String::createWithFormat("Unselected")->getCString());
            break;

        default:
            break;
    }
}

In Lua:

1
2
3
4
5
6
7
local function selectedEvent(sender,eventType)
        if eventType == ccui.CheckBoxEventType.selected then
            self._displayValueLabel:setString("Selected")
        elseif eventType == ccui.CheckBoxEventType.unselected then
            self._displayValueLabel:setString("Unselected")
        end
    end  

There are two statuses for a checkbox-selected and unselected. It changes its status when it is touched, we can call some callback functions to do something. As shown, when the status changed, it will call the function to inform the checkbox.

uicheckboxs

Slider

It's a good choice to choose slider if you want to add a widget controlling the volume.

In C++:

1
2
3
4
5
6
7
8
9
10
11
 // Create the slider
        Slider* slider = Slider::create();
        slider->loadBarTexture("cocosui/sliderTrack2.png");
        slider->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "");
        slider->loadProgressBarTexture("cocosui/slider_bar_active_9patch.png");
        slider->setScale9Enabled(true);
        slider->setCapInsets(Rect(0, 0, 0, 0));
        slider->setContentSize(Size(250.0f, 19));
        slider->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f/* + slider->getSize().height * 3.0f*/));
        slider->addEventListener(CC_CALLBACK_2(UISliderTest_Scale9::sliderEvent, this));
        _uiLayer->addChild(slider);

In Lua

1
2
3
4
5
6
7
8
9
local slider = ccui.Slider:create()
    slider:setTouchEnabled(true)
    slider:loadBarTexture("cocosui/sliderTrack.png")
    slider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "")
    slider:loadProgressBarTexture("cocosui/sliderProgress.png")
    slider:setPosition(cc.p(widgetSize.width / 2.0, widgetSize.height / 2.0))
    slider:addEventListener(percentChangedEvent)

    self._uiLayer:addChild(slider)

uislider

We take different ways to load images, loadBarTexture for slider background image and loadSlidBallTextures for three statuses image of slider. That is the center ball can be dragged. However, loadProgressBarTexture method displaying the progress of the slider. It also has callback function, which can be used for record current status:

In C++:

1
2
3
4
5
6
7
8
9
10
void UISliderTest::sliderEvent(Ref *pSender, Slider::EventType type)
{
    if (type == Slider::EventType::ON_PERCENTAGE_CHANGED)
    {
        Slider* slider = dynamic_cast<Slider*>(pSender);
        int percent = slider->getPercent();
        _displayValueLabel->setString(String::createWithFormat("Percent %d", percent)->getCString());
    }
}

In Lua:

1
2
3
4
5
6
7
local function percentChangedEvent(sender,eventType)
        if eventType == ccui.SliderEventType.percentChanged then
            local slider = sender
            local percent = "Percent " .. slider:getPercent()
            self._displayValueLabel:setString(percent)
        end
    end  

By dynamic cast pSender to get UISlider, then get the percentage of UISlider to save UI resource by using squared picture.

LoadingBar

In contrast to the slider is a progress bar, one of them is controlling progress manually then return value and the other is setting value manually then update displaying. For example, when we loading some image resource the progress can show us the loading progress. Following is one usage:

In C++:

1
2
3
4
5
6
7
    LoadingBar* loadingBar = LoadingBar::create();
    loadingBar->setName("LoadingBar");
    loadingBar->loadTexture("cocosgui/sliderProgress.png");
    loadingBar->setPercent(0);

    loadingBar->setPosition(Point(widgetSize.width / 2.0f, widgetSize.height / 2.0f + loadingBar->getSize().height / 4.0f));
    m_pUiLayer->addChild(loadingBar);

In Lua:

1
2
3
4
5
 local loadingBar = ccui.LoadingBar:create()
    loadingBar:setTag(0)
    loadingBar:setName("LoadingBar")
    loadingBar:loadTexture("cocosui/sliderProgress.png")
    loadingBar:setPercent(0)

uiloadingbar

We did some initialize work above, if you want to get new value in real time then you need to update the value by setPercent method. When run a scene, we call the scheduleUpdate(); and implement update method ensuring it can be called every frame. Following code should be in update method:

In C++:

1
2
3
4
5
6
7
8
9
10
11
    void UILoadingBarTest_Left::update(float delta)
    {
        m_nCount++;
        if (m_nCount > 100)
        {
            m_nCount = 0;
        }

        UILoadingBar* loadingBar = dynamic_cast<UILoadingBar*>(m_pUiLayer->getWidgetByName("LoadingBar"));
        loadingBar->setPercent(m_nCount);
    }

In Lua:

1
2
3
4
5
6
7
8
9
10
11
local function update(delta)
        self._count = self._count + 1
        if self._count > 100 then
            self._count = 0
        end

        if self._uiLayer ~= nil then
            local loadingBar = self._uiLayer:getChildByTag(0)
            loadingBar:setPercent(self._count)
        end
    end

It's a increase number start from zero, you can see from left to right the length of process bar is increasing. If you want the process bar's length increasing from right from left, you can set loadingBar->setDirection(LoadingBarTypeRight); and this widget support squared picture.

TextAtlas

UILabelAtlas can display number label that jointed by images:

In C++:

1
2
3
4
 // Create the text atlas
        TextAtlas* textAtlas = TextAtlas::create("1234567890", "cocosui/labelatlas.png", 17, 22, "0");
        textAtlas->setPosition(Vec2((widgetSize.width) / 2, widgetSize.height / 2.0f));
        _uiLayer->addChild(textAtlas); 

In Lua:

1
2
3
4
5
  local labelAtlas = ccui.TextAtlas:create()
    labelAtlas:setProperty("1234567890", "cocosui/labelatlas.png", 17, 22, "0")
    labelAtlas:setPosition(cc.p((widgetSize.width) / 2, widgetSize.height / 2.0))        

    self._uiLayer:addChild(labelAtlas) 

uilabelatlas

The usage of this widget is very simple, Label is not efficient in old version so LabelAtlas is a good substitution but in version 3.0 Label has been improved a lot. Here we choose Atlas because we can custom it to get better displaying effect.

TextBMFont

In addition to UILabelAtlas, you can also display a label by UILabelBMFont.

In C++:

1
2
3
4
  // Create the TextBMFont
        TextBMFont* textBMFont = TextBMFont::create("BMFont", "cocosui/bitmapFontTest2.fnt");
        textBMFont->setPosition(Vec2(widgetSize.width / 2, widgetSize.height / 2.0f + textBMFont->getContentSize().height / 8.0f));
        _uiLayer->addChild(textBMFont);

In Lua:

1
2
3
4
5
6
  local labelBMFont = ccui.TextBMFont:create()
    labelBMFont:setFntFile("cocosui/bitmapFontTest2.fnt")
    labelBMFont:setString("BMFont")
    labelBMFont:setPosition(cc.p(widgetSize.width / 2, widgetSize.height / 2.0 + labelBMFont:getContentSize().height / 8.0))        

    self._uiLayer:addChild(labelBMFont) 

uibmfont

Just like TextlAtlas,TextBMFont store the display information by a image, but Atlas is smaller than BMFont. You can set the parameters of the cutting, but BMFont has to be with a ".fnt" file. There are many information in it, and it also provide many display effect.

Text

Text widget can help us solve some problems such as auto wrap and so on. It's important for design a flexible UI.

In C++:

1
2
3
4
5
6
7
8
  // Create the line wrap
        Text* text = Text::create("Text can line wrap","AmericanTypewriter",32);
        text->ignoreContentAdaptWithSize(false);
        text->setContentSize(Size(280, 150));
        text->setTextHorizontalAlignment(TextHAlignment::CENTER);
        text->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - text->getContentSize().height / 8.0f));
        _uiLayer->addChild(text);     

In Lua:

1
2
3
4
5
6
7
8
local textArea = ccui.Text:create()
    textArea:setTextAreaSize(cc.size(280, 150))
    textArea:setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_CENTER)
    textArea:setString("TextArea widget can line wrap")
    textArea:setFontName("AmericanTypewriter")
    textArea:setFontSize(32)
    textArea:setPosition(cc.p(widgetSize.width / 2, widgetSize.height / 2 - textArea:getContentSize().height / 8))  
    self._uiLayer:addChild(textArea) 

uitextarea

You need to know the size of a text area, and its alignmet(Use setTextHorizontalAlignment to set the align mode: Left, Right and Center), display content, font size and font etc.

TextField

Text Field is a very important widget, it can call device's input system to receive user's input content such as user name and password in a login scene.

In C++:

1
2
3
4
5
6
7
8
9
 // Create the textfield
        TextField* textField = TextField::create("input words here","fonts/Marker Felt.ttf",30);
        textField->ignoreContentAdaptWithSize(false);
        textField->setContentSize(Size(240, 160));
        textField->setTextHorizontalAlignment(TextHAlignment::CENTER);
        textField->setTextVerticalAlignment(TextVAlignment::CENTER);
        textField->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f));
        textField->addEventListener(CC_CALLBACK_2(UITextFieldTest_LineWrap::textFieldEvent, this));
        _uiLayer->addChild(textField);

In Lua:

1
2
3
4
5
6
7
8
 local textField = ccui.TextField:create()
    textField:setTouchEnabled(true)
    textField:setFontName(font_UITextFieldTest)
    textField:setFontSize(30)
    textField:setPlaceHolder("input words here")
    textField:setPosition(cc.p(widgetSize.width / 2.0, widgetSize.height / 2.0))
    textField:addEventListener(textFieldEvent) 
    self._uiLayer:addChild(textField) 

uitextfield

Setted properties and enabled touch, then wait user's touch event to done the text input work. setPlaceHolder can remind user to input when the widget don't show anything. Notice that the callback functions here have many statuses:

In C++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
   void UITextFieldTest_LineWrap::textFieldEvent(Ref *pSender, TextField::EventType type)
{
    switch (type)
    {
        case TextField::EventType::ATTACH_WITH_IME:
        {
            TextField* textField = dynamic_cast<TextField*>(pSender);
            Size widgetSize = _widget->getContentSize();
            textField->runAction(CCMoveTo::create(0.225f,
                                                  Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f + textField->getContentSize().height / 2)));
            textField->setTextHorizontalAlignment(TextHAlignment::LEFT);
            textField->setTextVerticalAlignment(TextVAlignment::TOP);

            _displayValueLabel->setString(CCString::createWithFormat("attach with IME")->getCString());
        }
            break;

        case TextField::EventType::DETACH_WITH_IME:
        {
            TextField* textField = dynamic_cast<TextField*>(pSender);
            Size widgetSize = _widget->getContentSize();
            textField->runAction(CCMoveTo::create(0.175f, Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)));
            textField->setTextHorizontalAlignment(TextHAlignment::CENTER);
            textField->setTextVerticalAlignment(TextVAlignment::CENTER);

            _displayValueLabel->setString(CCString::createWithFormat("detach with IME")->getCString());
        }
            break;

        case TextField::EventType::INSERT_TEXT:
            _displayValueLabel->setString(CCString::createWithFormat("insert words")->getCString());
            break;

        case TextField::EventType::DELETE_BACKWARD:
            _displayValueLabel->setString(CCString::createWithFormat("delete word")->getCString());
            break;

        default:
            break;
    }
}

In Lua:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 local function textFieldEvent(sender, eventType)
        if eventType == ccui.TextFiledEventType.attach_with_ime then
            local textField = sender
            local screenSize = cc.Director:getInstance():getWinSize()
            textField:runAction(cc.MoveTo:create(0.225,cc.p(screenSize.width / 2.0, screenSize.height / 2.0 + textField:getContentSize().height / 2.0)))
            self._displayValueLabel:setString("attach with IME")
        elseif eventType == ccui.TextFiledEventType.detach_with_ime then
            local textField = sender
            local screenSize = cc.Director:getInstance():getWinSize()
            textField:runAction(cc.MoveTo:create(0.175, cc.p(screenSize.width / 2.0, screenSize.height / 2.0)))
            self._displayValueLabel:setString("detach with IME")
        elseif eventType == ccui.TextFiledEventType.insert_text then
            self._displayValueLabel:setString("insert words")
        elseif eventType == ccui.TextFiledEventType.delete_backward then
            self._displayValueLabel:setString("delete word")
        end
    end

First, it have four event type:

Event Type Description
TextField::EventType::ATTACH_WITH_IME Enable trigger when input
TextField::EventType::DETACH_WITH_IME Trigger when event end
TextField::EventType::INSERT_TEXT Trigger when insert text
TextField::EventType::DELETE_BACKWARD Trigger when delete text

Accroding to the event type, we can get widget's content or change widget's properties in real time. We can set widget's max text length by textField->setMaxLength(3);.

In a login scene, we usually design a user name box and a password box, and the widget absolutely support password box's property:

In C++:

1
2
    textField->setPasswordEnabled(true);
    textField->setPasswordStyleText("*");

In Lua:

1
2
  textField:setPasswordEnabled(true)
  textField:setPasswordStyleTest("*")

Enable password mode first, and then set a substitute character.

uislider.png (88.3 kB) owen, 2014-04-02 07:13

uitextarea.png (99.6 kB) owen, 2014-04-02 07:13

uitextbutton.png (93.9 kB) owen, 2014-04-02 07:13

uitextbutton9.png (96.7 kB) owen, 2014-04-02 07:13

uibmfont.png (95 kB) owen, 2014-04-02 07:13

uicheckbox.png (91.7 kB) owen, 2014-04-02 07:13

uicheckboxs.png (90.5 kB) owen, 2014-04-02 07:13

uilabelatlas.png (91.4 kB) owen, 2014-04-02 07:13

uitextfield.png (85.5 kB) owen, 2014-04-02 07:13

uiloadingbar.png (86.7 kB) owen, 2014-04-02 07:13

Sign up for our newsletter to keep up with the latest developments, releases and updates for Cocos2d-x.