cocos2dx-ui的分類與使用

容器層的使用

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();

    UILayout *background = dynamic_cast<UILayout*>(m_pUiLayer->getWidgetByName("background_Panel"));

    // Create the layout
    UILayout* layout = UILayout::create();
    layout->setSize(Size(280, 150));
    Size backgroundSize = background->getSize();
    layout->setPosition(Point((widgetSize.width - backgroundSize.width) / 2 +
                            (backgroundSize.width - layout->getSize().width) / 2,
                            (widgetSize.height - backgroundSize.height) / 2 +
                            (backgroundSize.height - layout->getSize().height) / 2));
    m_pUiLayer->addWidget(layout);

    UIButton* button = UIButton::create();
    button->setTouchEnabled(true);
    button->loadTextures("cocosgui/animationbuttonnormal.png", "cocosgui/animationbuttonpressed.png", "");
    button->setPosition(Point(button->getSize().width / 2, layout->getSize().height - button->getSize().height / 2));
    layout->addChild(button);

    UIButton* textButton = UIButton::create();
    textButton->setTouchEnabled(true);
    textButton->loadTextures("cocosgui/backtotopnormal.png", "cocosgui/backtotoppressed.png", "");
    textButton->setTitleText("Text Button");
    textButton->setPosition(Point(layout->getSize().width / 2, layout->getSize().height / 2));
    layout->addChild(textButton);

    UIButton* button_scale9 = UIButton::create();
    button_scale9->setTouchEnabled(true);
    button_scale9->loadTextures("cocosgui/button.png", "cocosgui/buttonHighlighted.png", "");
    button_scale9->setScale9Enabled(true);
    button_scale9->setSize(Size(100, button_scale9->getContentSize().height));
    button_scale9->setPosition(Point(layout->getSize().width - button_scale9->getSize().width / 2, button_scale9->getSize().height / 2));
    layout->addChild(button_scale9);

如上面代碼所示,我們創建了一個 layout 控件,然後在其中添加了三個控件。m_pUiLayer 是當前場景的一個 UILayer ,前面我們介紹過,所有的 UI 控件,都是放在 UILayer 裏面,UILayer 管理所有的控件,並添加到當前場景中去。顯示效果如下:

uipanel_test

我們設置了 layout 的 size 屬性,也就是給它一個大小,但是並沒有顯示出來效果,默認是透明的,我們可以爲這個層設置顏色:

    layout->setBackGroundColorType(LAYOUT_COLOR_SOLID);
    layout->setBackGroundColor(Color3B(128, 128, 128));

uipanel_color

除了設置純色之外,還可以設計漸變顏色:

    layout->setBackGroundColorType(LAYOUT_COLOR_GRADIENT);
    layout->setBackGroundColor(Color3B(64, 64, 64), Color3B(192, 192, 192));

uipanel_gradient

當然,除了設置顏色之外,還可以設置我們想要的背景圖片:

    layout->setSize(Size(280, 150));

    layout->setClippingEnabled(true);
    layout->setBackGroundImage("cocosgui/Hello.png");

uipanel_background1

如上圖顯示,我們設置了 size 並且設置了 背景圖片,但是不要忘了調用 setClippingEnabled 方法根據 size 進行裁剪,如果忘了調用,那麼會向下面所顯示的一樣。

uipanel_background2

除了以上使用方式,還有其它玩法:

    layout->setBackGroundImageScale9Enabled(true);
    layout->setBackGroundImage("cocosgui/green_edit.png");

uipanel_scale9

使用九宮格圖片做爲背景,注意啓用此功能。

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(LAYOUT_LINEAR_VERTICAL);

    // 或者
    layout->setLayoutType(LAYOUT_LINEAR_HORIZONTAL);

    // 或者
    layout->setLayoutType(LAYOUT_RELATIVE);

注意:除了絕對定位之外,如果設置了其它佈局方案,那麼 UIPanel 會忽略其內部控件本身設置的位置。而此時可以使用提供的 UILayoutParameter 來設置位置關係,根據佈局方案提供了幾種佈局參數, UILinearLayoutParameter 和 UIRelativeLayoutParameter。下面介紹如何實用佈局參數來配合佈局設計界面顯示效果。

    layout->setLayoutType(LAYOUT_LINEAR_VERTICAL);

    // .... 省略控件創建代碼,同前文控件一樣

    UILinearLayoutParameter* lp1 = UILinearLayoutParameter::create();
    lp1->setGravity(LINEAR_GRAVITY_CENTER_HORIZONTAL);
    lp1->setMargin(UIMargin(0, 10, 0, 10));

    UILinearLayoutParameter* lp2 = UILinearLayoutParameter::create();
    lp2->setGravity(LINEAR_GRAVITY_CENTER_HORIZONTAL);
    lp2->setMargin(UIMargin(20, 20, 0, 5));

    UILinearLayoutParameter* lp3 = UILinearLayoutParameter::create();
    lp3->setGravity(LINEAR_GRAVITY_CENTER_HORIZONTAL);
    lp3->setMargin(UIMargin(0, 10, 0, 10));

    button->setLayoutParameter(lp1);
    textButton->setLayoutParameter(lp2);
    button_scale9->setLayoutParameter(lp3);

顯示效果如下:

uipanel_vertical

我們看到,分別創建了三個佈局參數 UILinearLayoutParameter,設置了 Gravity 和 Margin 參數,然後給三個 UIPanel 的內部控件分別設置其佈局參數值,已達到如上效果。

這裏使用的方案是垂直平鋪,而每個佈局參數設置的 Gravity 值爲 LINEAR_GRAVITY_CENTER_HORIZONTAL,也就是說水平劇中顯示,而 Margin 則標示控件四周邊緣的間距,注意以上的 lp2 的值爲 UIMargin(20, 20, 0, 5),其代表含義,距離左、上、右、下的間距。左值爲 20,可以看見 textButton 相對中間位置向右便宜少數。這是垂直佈局,而水平佈局除了方向不一,基本使用方式同垂直佈局同樣。兩者也都叫 線性佈局,使用同樣的線性佈局參數。下面再看看相對佈局:

    layout->setLayoutType(LAYOUT_RELATIVE);

    // 此處省略控件的創建步驟 ...

    UIRelativeLayoutParameter* rp1 = UIRelativeLayoutParameter::create();
    rp1->setAlign(RELATIVE_ALIGN_PARENT_TOP_RIGHT);

    UIRelativeLayoutParameter* rp2 = UIRelativeLayoutParameter::create();
    rp2->setAlign(RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL);

    UIRelativeLayoutParameter* rp3 = UIRelativeLayoutParameter::create();
    rp3->setAlign(RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM);

    button->setLayoutParameter(rp1);
    textButton->setLayoutParameter(rp2);
    button_scale9->setLayoutParameter(rp3);

uipanel_relative

這裏創建了三個佈局屬性,設置了不同的 "停靠" 參數 Align 。

UIScrollView 滾動視圖

除了佈局容器,我們常用的還有滾動層容器,它可以擴大我們的顯示控件,當內容元素很多時,尤爲有用。可以設置爲兩個方向,橫向或者是豎向。

    UIScrollView* scrollView = UIScrollView::create();
    scrollView->setTouchEnabled(true);
    scrollView->setSize(Size(280, 150));        
    Size backgroundSize = background->getContentSize();
    scrollView->setPosition(Point((widgetSize.width - backgroundSize.width) / 2 +
                           (backgroundSize.width - scrollView->getSize().width) / 2,
                           (widgetSize.height - backgroundSize.height) / 2 +
                           (backgroundSize.height - scrollView->getSize().height) / 2));


    m_pUiLayer->addWidget(scrollView);

    UIImageView* imageView = UIImageView::create();
    imageView->loadTexture("cocosgui/ccicon.png");

    float innerWidth = scrollView->getSize().width;
    float innerHeight = scrollView->getSize().height + imageView->getSize().height;

    scrollView->setInnerContainerSize(Size(innerWidth, innerHeight));    

    imageView->setPosition(Point(innerWidth / 2, imageView->getSize().height / 2));
    scrollView->addChild(imageView);

    // 爲 scrollview 添加其它控件,省略

uiscrollview_vertical

請看如圖效果,這裏創建了一個 ScrollView 控件,並且添加了一些內部元素,以完成佈局,控件內容超出顯示區域,我們可以通過上下拖動,來顯示上下未未顯示的不分。

注意: imageView 設置的位置在 scrollview 之外,可以通過 scrollview 的 setInnerContainerSize 方法設置包含內容的區域大小,在拖動的過程中,邊界檢查。

如果是設置橫向的拖動效果,我們只需要設置 InnerContainerSize 的 寬度大於控件的大小,高度相同,就能實現橫向的拖動效果。

UIListView

ListView 繼承自 ScrollView,所以 ScrollView 裏面有的功能,特性,在 ListView 中也都能體現出來。那麼 ListView 相比較 ScrollView 多了些什麼呢?還是先從使用方法上開始:

    UIListView* lv = UIListView::create();
    UIButton* model = UIButton::create();
    model->loadTextures("cocosgui/animationbuttonnormal.png", "cocosgui/animationbuttonpressed.png", "");
    lv->setItemModel(model);

    for (int i=0; i<20; i++)
    {
        lv->pushBackDefaultItem();
    }
    lv->setItemsMargin(10);
    lv->setGravity(LISTVIEW_GRAVITY_CENTER_HORIZONTAL);
    lv->setSize(Size(100, 100));
    lv->setBackGroundColorType(LAYOUT_COLOR_SOLID);
    lv->setBackGroundColor(Color3B::GREEN);
    lv->setPosition(Point(100, 100));
    m_pUiLayer->addWidget(lv);

uilistview_vertical

如圖,但不能很好的看到效果,這裏是類似 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();
    pageView->setTouchEnabled(true);
    pageView->setSize(Size(240, 130));
    Size backgroundSize = background->getContentSize();
    pageView->setPosition(Point((widgetSize.width - backgroundSize.width) / 2 +
                              (backgroundSize.width - pageView->getSize().width) / 2,
                              (widgetSize.height - backgroundSize.height) / 2 +
                              (backgroundSize.height - pageView->getSize().height) / 2));

    for (int i = 0; i < 3; ++i)
    {
        UILayout* layout = UILayout::create();
        layout->setSize(Size(240, 130));

        UIImageView* imageView = UIImageView::create();
        imageView->setTouchEnabled(true);
        imageView->setScale9Enabled(true);
        imageView->loadTexture("cocosgui/scrollviewbg.png");
        imageView->setSize(Size(240, 130));
        imageView->setPosition(Point(layout->getSize().width / 2, layout->getSize().height / 2));
        layout->addChild(imageView);

        UILabel* label = UILabel::create();
        label->setText(CCString::createWithFormat("page %d", (i + 1))->getCString());
        label->setFontName(font_UIPageViewTest);
        label->setFontSize(30);
        label->setColor(Color3B(192, 192, 192));
        label->setPosition(Point(layout->getSize().width / 2, layout->getSize().height / 2));
        layout->addChild(label);

        pageView->addPage(layout);
    }
    pageView->addEventListenerPageView(this, pagevieweventselector(UIPageViewTest::pageViewEvent));

    m_pUiLayer->addWidget(pageView);

uipageview

如圖顯示,創建了一個 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 ,根據實際的需要靈活的組織可以讓我們的界面顯示的更爲友好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章