duilib各種布局的作用,相對布局與絕對布局的的意義與使用方法


轉載請說明原出處,謝謝~~


       我使用duilib快3個月了。總體感覺duilib的使用還是較為簡單的,僅僅是剛入門時可能有些摸不清頭腦。今天寫一篇關於duilib的入門日志,大致說一下duilib中的各個布局的作用,以及非常關鍵的相對布局與絕對布局的意義與使用方法。

希望能夠幫到使用duilib的新手朋友們。duilib高手就能夠直接省略這篇文章了!


      我剛使用duilib的時候非常依賴duilib自帶的設計器,用他能夠拖拉控件。可視化的做出自己想要的界面。可是用一段時間就會發現原帶的設計器有非常多bug,時不時會崩潰,支持的控件數量有限,屬性數量也有限,導出的代碼冗余。當時問了幾個高手,大家建議不要使用設計器而應該自己手寫xml代碼。

起初手寫時感覺特別麻煩,可是用幾天后你會發現手寫要比使用設計器好得多:你能夠更加了解duilib,熟悉每一個控件的各個屬性。對控件的控制也更加方便。而假設想稱心如意的脫離設計器去編寫xml文件,有非常有必要弄明白各個布局的使用方法和布局技巧。

我如今能夠全然靠手寫xml來做出一個程序的界面,相信用了一段duilib的朋友也是這樣。


     在這里提醒一下新手朋友,在duilib的根文件夾有一個屬性列表.xml的文件,他包括了絕大多數控件的絕大多數屬性的介紹,有不懂的屬性記得時常翻看他。同一時候不得不說這個文件包括的屬性的確是不全面的,想要知道最全面的屬性信息,能夠看每一個控件的源代碼。在SetAttribute函數中能夠看到最全面的屬性信息。


      要想手寫xml,當然必須有一個編寫工具。原則上僅僅要是能夠編寫文本的工具都能夠。大家依據習慣自己挑選適合的工具。我眼下在使用的是sublime這款工具。感覺編寫xml非常方便,使用界面也不錯。


6大布局的作用:


      duilib的Layout文件夾專門放置布局相關的容器控件。這6個布局分別為:Container、VerticalLayout、HorizaontalLayout、TileLayout、TabLayout、ChildLayout。容器之間能夠隨意相互嵌套,我分別說明他們的使用方法。


      首先我要說明一下。以下介紹的時候,我都默認覺得每一個控件的float屬性為false,也就是不使用絕對定位,這個屬性會打破各個布局的作用。


    Container:


     Container布局是其它全部布局以及含有容器特性(如CList、CListContainerElement)的控件的基類,而實際上開發過程中非常少使用這個布局。僅僅用他來做其它更高級的布局的基類。由於Container布局中的全部控件都會自己主動填充滿整個布局,全部的控件都疊到了一起,假如恰好有什么需求要讓子控件都覆蓋起來。並且能夠隨着容器的改變而自適應填充的話,Container就是不二之選。而除了這個效果之外。一般我們不使用它。


     VerticalLayout、HorizaontalLayout:


     VerticalLayout與HorizaontalLayout布局無疑是duilib中最常使用的兩個布局,巧妙的使用這兩個布局能夠滿足大多數的布局需求。

從單詞的意思上不難看出VerticalLayout是縱向布局,HorizaontalLayout是橫向布局。這門兩個直接繼承自Container布局。


     VerticalLayout布局會讓他包括的元素都縱向排列開,HorizaontalLayout布局會讓給他包括的元素都橫向排列開:如圖


                                                           


        我有益沒讓控件填滿整個容器。為了說明這兩個布局不會強行讓子元素的總和去填滿容器,縱向布局會從上到下依據每一個控件的高度讓他們排到一起,橫向布局會從左到右依據每一個控件的寬度讓他們排到一起。

另外能夠看到,縱向布局僅僅關心子元素的高度,而不會強行讓子元素的寬度等於容器的寬度。這點從圖片能夠看到,橫向布局同理也是僅僅關心子元素的寬度。

而這兩個布局經常會嵌套使用。例如以下效果:




       能夠看到我最外層使用了一個縱向布局,他包括了橫縱橫三個布局(分別為紅綠藍顏色),每一個橫向布局里又分別包括了幾個button。我們在編寫界面時經經常使用到這種方法!以下是這個布局效果圖相應的xml代碼:


<?

xml version="1.0" encoding="utf-8" standalone="yes" ?> <Window size="300,226"> <VerticalLayout width="300" height="318" bkcolor="#FFFFFFFF"> <HorizontalLayout width="300" height="65" bkcolor="#FFFF0000"> <Button text="button測試" width="60" height="35" /> <Button text="button測試" width="60" height="63" /> <Button text="button測試" width="60" height="35" /> </HorizontalLayout> <VerticalLayout width="300" height="96" bkcolor="#FF00FF00"> <Button text="button測試" width="60" height="64" /> <Button text="button測試" width="60" height="75" /> <Button text="button測試" width="60" height="64" /> </VerticalLayout> <HorizontalLayout width="300" height="65" bkcolor="#FF0000FF"> <Button text="button測試" width="60" height="47" /> <Button text="button測試" width="60" height="64" /> <Button text="button測試" width="60" height="64" /> </HorizontalLayout> </VerticalLayout> </Window>


       TileLayout:


       TileLayout布局是用來做相似360工具箱的效果:




       在前面的文章里,我寫的duilib中ListCtrl控件的實現仿酷狗音樂播放器開發日志十三——左側功能塊的完好正是使用了這個布局完畢的。這個布局有有兩個關鍵屬性:


		<Attribute name="columns" default="1" type="INT" comment="列數,如(4)"/>
		<Attribute name="itemsize" default="0,0" type="SIZE" comment="子項固定大小。如(128,128)"/>

 

       columns和itemsize屬性,這兩個屬性不能一起用。應該僅僅是用當中的一個。

使用columns屬性能夠來設置每行中包括的列數。他會自己主動把包括的元素從左到右從上到下依照columns屬性的設置排列起來,他把每行的列數固定死了。而itemsize有兩個字段,通過我讀源代碼,發現第二個字段是無效的。我們僅僅要使用第一個字段即可了,他會設置每一個元素所占的區域。比方容器的寬度是500,給itemsize設置為 100 x 10,那個每行就會容納5個元素,當我們拉伸了窗口讓容器寬度變為700。那么每行就會自己主動容納7個元素,這意味着使用這個屬性會讓每行容納的元素個數是自己主動可變的!這在非常多情況下是非常實用的屬性。注意itemsize並非直接設置了子控件的大小。而僅僅是限制了子控件的最大區域。比方itemsize為100x100。而子控件設置為50x50。那么 終於的子控件大小為50x50,而子控件的位置會依照100x100來計算。這個希望讀者自己實踐一下來理解這個效果!


     TabLayout:


     TabLayout布局相同經常使用,他就像MFC的選項卡CTabCtrl控件。如圖:




      可是在duilib中TabLayout僅僅是以下的布局界面,而不包括頂端的選項卡button。所以經經常使用Option控件配合他一起使用,使用他時他會把他包括的下一級元素作為一個頁面,所以我們通常在他里面放入橫縱向布局來作為一個頁面,在橫縱向布局里再規划每一個頁面的外觀。


      這個控件的具體使用方法大家能夠看duilib自帶的360demo,我就不贅述了!


      ChildLayout:


      ChildLayout布局比較少用,由於他的功能能夠用其它布局來取代,他的作用就是從一個xml文件里載入布局來嵌入到ChildLayout布局所在的地方,使用這個布局一般僅僅須要指定xmlfile屬性來設置xml文件位置就能夠了。他的意義在於能夠把繁雜的大量xml代碼分隔開。比方他和TabLayout布局結合,讓TabLayout布局包括5個ChildLayout布局,而每一個ChildLayout布局分別從5個xml文件載入自己的布局文件,這樣就能夠分塊化的編寫布局代碼。


      實際上有個比他更好用的標簽,就是Include標簽。Include不屬於布局,但他的作用在布局方面非常相似ChildLayout,指定他的Source屬性到某個xml文件就能夠了。相對ChildLayout,Include的長處是能夠自己主動識別自己定義控件,而ChildLayout不能夠!


      在這里要提一下360Demo的自己定義控件。這個demo的自己定義控件做法誤導了非常多人,里面使用了自己定義控件的方法,把一個xml布局文件嵌入到界面里。這樣的做法全然不是必需,直接使用Include標簽,一句xml代碼能夠全然取代自己定義控件。


      這里給出一個Include的使用方法:

<Include source="Login\ScrollBar.xml" count="1" />


      當中source屬性指定xml文件的路徑。count指定解析的次數。


絕對布局的意義與使用方法:


       在知道了6大布局的使用方法之后,知道了各種樣式的界面外觀的大致布局方法,而這還遠不夠讓我們寫出美麗的布局外觀。僅僅有配合相對布局與絕對布局才干夠更好的控制界面的元素。

值得一提的是。我這里說的相對布局和絕對布局並非一個容器或者控件,這僅僅是一種技巧和使用方法,用在容器布局所包括的控件上,經常使用到橫縱向布局中。


      我先來介紹絕對布局,籠統上說絕對布局和相對布局事實上僅僅有一個區別。也就是我在前面提到的float屬性。容器中包括的控件float屬性為真就是絕對布局。為假就是相對布局。不要小看這一個屬性,他帶來的效果能夠天差地別。


      給控件的float屬性設為真后,就使用了絕對布局,故名意思,絕對布局就是讓控件的坐標絕對化,這樣這個控件就不受他的容器的束縛而能夠自己隨意設置自己的位置!

比方在橫縱向布局中給他們包括的子控件設置float屬性,這個控件就不會被自己主動橫縱向排列。而我的建議是。能不用絕對布局就別用絕對布局!

原因有三個:


      1)絕對布局破壞了各個容器的特性。而不受容器的束縛。

      2)絕對布局讓控件的坐標固定,不利於控件自己主動調節位置。

      3)后面提到的相對布局差點兒能夠完畢絕對布局的全部特性。


     那么為什么要用絕對布局,由於他的一個功能是相對布局無法完畢的。就是讓控件或者布局重疊或者相交!

有的時候我們必須這樣做來讓控件組合起來達到一些效果。我能夠明白的說。我在做仿酷狗播放器的過程中,整個xml布局代碼僅僅用了2個絕對布局。一個是編寫搜索欄仿酷狗音樂播放器開發日志二——搜索欄的編寫,一個是編寫電台控件。如圖:



 

       另外一個非常經典的使用絕對布局的樣例就是我前幾天寫的用duilib制作仿QQ2013動態背景登錄器。這些樣例都是由於要讓控件重疊起來組合出新的控件才使用了絕對布局。假設不讓控件重疊或者沒有特殊需求,最好別用絕對布局。


        盡管不建議使用,但我也得說一下絕對布局相關的屬性和使用技巧。

        1)把float屬性設置為真。

        2)設置pos屬性,這個屬性在float為真時才有效,他包括四個字段。分別以為了控件的左上右下下個坐標的位置,可是建議僅僅指定前兩個字段來設置控件的左上角的坐標。控件的寬度用width和height屬性來控制。這樣做的長處是避免了計算右下角坐標的繁瑣!以后改動的時候也非常清晰。


        舉出一個樣例:

<Label name="MusicName" float="true" pos="100,100" width="26" height="22" textcolor="#FF505050" endellipsis="true" />

        這里設置了一個Label控件,左上角放到100,100的坐標上。控件高22。寬26

        不得不提一個非常實用的屬性,那就是relativepos屬性,屬性列表沒有列出這個屬性,這是我自己總結的


<Attribute name="relativepos" default="0,0,0,0" type="RECT" comment="設置相對移動。float為真時,分別表示橫縱向位移值。橫縱向縮放值,移動單位建議50或100"/>

        用了這個屬性,就能夠讓控件擁有相對布局的一部分特性,那就是依據容器的大小,自己能夠調整位置和大小!這個特點我在仿酷狗音樂播放器開發日志二——搜索欄的編寫用到了,是為了讓搜索button能夠自己移動。這個屬性的前兩個字段表示橫縱向的位移值。后兩個字段表示縮放值,具體效果大家應該自己實踐一下!另外這個屬性默認是有嚴重bug的,就是窗口最小化再恢復后有這個屬性的控件會自己主動無規律偏移。這個bug我修復了。詳見仿酷狗音樂播放器開發日志二——搜索欄的編寫


        這樣就介紹完了絕對布局。然后就是整片文章的最重要部分。相對布局。


相對布局的意義與使用方法:


       我把相對布局的介紹放到最后。由於它非常重要。


       在容器內部使用控件或者容器時。float屬性設置為flase(duilib默覺得false)就是相對布局了。這是我非常推薦使用的,前面我也說了我在寫仿酷狗的整個布局中,上百個控件中我僅僅給兩個控件使用了絕對布局。其余都是相對布局。

他的長處例如以下:


        1)布局和控件是能夠依據窗口的大小改變而自己主動調整位置的,這點非常重要

        2)不須要絕對布局那樣麻煩的計算各個控件的位置

        3)在容器中調整前一個控件的位置,后面的控件都會自己主動調整坐標


      事實上總得來說使用相對布局意義就是使用布局控件的自己主動排列特性!


      使用了相對布局后,就不用設置float屬性和pos屬性,一般僅僅設置甚至不設置width和height屬性。

這點非常重要。假設你的控件或者布局的大小是固定的,那么就設置width和height屬性。假設想讓控件或者布局依據窗口的大小而自己主動調整大小和位置,就不設置這兩個屬性。假設僅僅設置了一個屬性,比方width設置為100,而height不設置,那么他的高度是自己主動調整的而寬度是固定的。

父容器會自己主動安排他包括的元素,讓含有width和height屬性的控件占領相應的大小,把剩下的空間都分配給沒有設置wieth和height屬性的容器或者控件里。看以下一個樣例:


<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="300,300">
    <VerticalLayout name="Father">
        <HorizontalLayout name="Sub1" height="50" >
        </HorizontalLayout>


        <VerticalLayout name="Sub2">
        </VerticalLayout>


        <HorizontalLayout name="Sub3" height="50" >
        </HorizontalLayout>
    </VerticalLayout>
</Window>

   

      能夠看到窗口的大小為300x300。而最外層的是一個名為Fahter的縱向容器,包括三個子容器。而Father沒有指定width和height,所以當我改變了窗口的大小時,Father會自己主動調整自己的大小到和窗口大小相同,而三個子容器我都眉頭指定width屬性。所以三個子容器的寬度和Father是一樣。也就是他們的寬度都是和窗口寬度一樣,並且會自己主動調整。Sub1和Sub3的高度設置為50,所以他們的高度就固定了,而Sbu2的高度也沒有指定,那他會自己主動占領了除了Sub1和Sub2的全部空間!事實上這個樣例的布局是非經常見的界面布局樣例。比方說酷狗。sub1和sub3分別表示標題欄和狀態欄,sub2為程序的主界面:




       關於酷狗的更加具體的布局分析能夠看我前面寫的博客仿酷狗音樂播放器開發日志——總體框架分析。差點兒每開發酷狗的一部分,我都會把布局分析一下寫出來。


      把這些知識綜合起來。如今就能夠寫出一個自己主動調整大小的大致布局了,可是還沒法精確控制每一個控件的位置。


      利用上面介紹的自己主動占位的特性。我這里舉一個標題欄編寫的樣例:


<HorizontalLayout name="background" height="30" bkimage="file='UI\BKImage\4.jpg' source='0,0,1000,30'" ><!-- 標題欄 -->
        <Label text="皮膚與窗口調整——Redrain播放器" textcolor="#FFFFFFFF" textpadding="5,0,0,0" font="1" autocalcwidth="false" width="300"/>
	<Control />
	<Button name="closebtn" width="23" height="18" padding="0,6,0,0" normalimage="UI\title\close_normal.png" hotimage="UI\title\close_hover.png" pushedimage="UI\title\close_down.png" />                     
</HorizontalLayout>


       這個樣例是我的仿酷狗播放器的換膚窗口的標題欄。他的外層是一個橫向布局。高度為30,寬度隨窗口調整。讓標題文字居於左側,關閉button在最右側,假設讓窗口調整寬度后文字和關閉button自己主動調整位置。就須要把中間的空位占滿。

這時我們就須要一個占位控件,不給他設置width和height屬性。這樣子他就會自己主動占領剩余的空間!就達到了相對布局的自己主動調整位置的效果。這個使用方法是相對布局里非經常常使用的!

而這個占位控件在沒有什么其它要求時建議像我給出的樣例那樣。使用Control控件,由於他是全部控件和容器的祖先基類,代碼和屬性相對是最少的,這樣有利於提高程序的效率。


       在充分理解了占位的技巧后。再配合一些微調屬性,就能夠完美控制各個控件了,這幾個微調屬性各自是inset、padding、childpadding,這幾個屬性的介紹例如以下:


<Attribute name="padding" default="0,0,0,0" type="RECT" comment="外邊距,如(2,2,2,2)"/>
<Attribute name="inset" default="0,0,0,0" type="RECT" comment="容器的內邊距,如(2,2,2,2)"/>
<Attribute name="childpadding" default="0" type="DWORD" comment="子控件之間的額外距離,如(4)"/>

      在float為假,也就是相對布局中,這幾個屬性才起效。


      inset屬性


      這是給容器控件使用的。使用后他所包括的全部使用相對布局的元素。都會被限制在設置的范圍內,適合對容器內所用元素進行總體的坐標控制。

比方在前面提到的做360工具箱時。我們使用TileLayout容器來存放每一個工具,我們首先設置inset屬性。就能夠讓全部的工具項限制在一定范圍內,樣例例如以下:


<TileLayout name="listctrl" width="540" height="400" inset="20,20,0,20" childpadding="20" vscrollbar="true" columns="2" bkimage="CustomList\List_bk.png" itemhotimage="CustomList\ListItem_bk_hover.png" itemselectedimage="CustomList\ListItem_bk_hover.png">
</TileLayout>


       通過設置inset屬性。讓全部元素限制在一定范圍內而不用反復設置每一個元素的屬性。


      childpadding屬性:


      childpadding屬性設置容器內每一個元素之間的間距,這個比較easy理解。上面的樣例中也用到了childpadding屬性。這個屬性在不同容器中代表不允許思,在橫向布局中代表子控件之間的橫向間隔,在縱向布局中代表子控件之間的縱向間隔。在TileLayout容器中代碼行與行之間的間隔!


      padding屬性:


      padding屬性是相對布局中最經常使用的屬性。用來設置相對於前一個控件的位置。這個屬性的控件位置微調的關鍵。

一般僅僅用他的前兩個字段,設置左邊距和上邊距,后兩個字段是無效的,或者說存在問題(為什么會有問題?請看源代碼)。只是使用這兩個字段就夠了。

這是我的仿酷狗播放器的狀態的布局代碼:


<HorizontalLayout height="30" inset="77,0,0,0" bkimage="UI\statusbar\status_bk.png"><!-- 狀態欄 -->
    <Button width="31" height="30" padding="0,0,0,0" normalimage="UI\statusbar\add_normal.png" hotimage="UI\statusbar\add_hover.png" pushedimage="UI\statusbar\add_down.png" />
    <Button width="31" height="30" padding="40,0,0,0" normalimage="UI\statusbar\locate_normal.png" hotimage="UI\statusbar\locate_hover.png" pushedimage="UI\statusbar\locate_down.png" />
    <Button width="31" height="30" padding="40,0,0,0" normalimage="UI\statusbar\search_normal.png" hotimage="UI\statusbar\search_hover.png" pushedimage="UI\statusbar\search_down.png" />
    <Button width="31" height="30" padding="40,0,0,0" normalimage="UI\statusbar\setting_normal.png" hotimage="UI\statusbar\setting_hover.png" pushedimage="UI\statusbar\setting_down.png" />
    <Control />
    <Label text="Redrain仿酷狗音樂盒DirectUI ^_^" textpadding="0,6,0,0" width="30" font="0" />
</HorizontalLayout>




      使用padding屬性,這是底部這四個button的相對位置。

假設我想總體讓這四個控件向右位移10像素,那么我僅僅要設置第一個button的padding屬性為padding="10,0,0,0",就能夠了。其它布局全然不須要改動。


結束語


     講到這里也就把布局的知識總結得幾乎相同了,對於duilib的新手朋友,建議多看看各個demo的布局文件,他們差點兒涵蓋了全部知識點。然后結合我總結的東西自己手動寫幾個布局代碼,相信非常快就能夠熟練編寫界面布局了。另外我的前面博客里經常會分析布局。大家也能夠看看。


     我使用duilib的時間也不算長。水平有限,文章中有什么錯誤或者描寫敘述不清,請留言給我,我會及時糾正。


      Redrain  2014.8.13


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM