前言
本文可能涉及到一些“專業(yè)”的知識,為了不影響閱讀,可以先閱讀入門篇或者看看我的自制皮膚Glass
如果有按照我的步驟一步一步來,入門篇的最后一定會出現(xiàn)一個“bug”,放一張圖回憶回憶:

其實(shí)這不是bug啦,只是基本操作。其原理是客戶端的渲染機(jī)制導(dǎo)致的,這里不做過多的講解。只需要了解:
最底層(最下面)的控件一定要有背景繪制,實(shí)際上我們的壁紙就是最底層那層繪制。后來我們加上壁紙的繪制,客戶端就表現(xiàn)正常了,就是這個原理。
概覽
本文將會主要講解這些知識點(diǎn),放張圖壓壓驚:

主要參考官方文檔以及自己的經(jīng)驗(yàn)。
簡單介紹
layout : 控件該在哪里出現(xiàn)
controls : 控件該干些什么
styles : 控件該長什么樣
color : 描述樣式中的顏色或某些特定的屬性值
一個完整的 .layout 文件由上面4部分構(gòu)成,每個部分都被一對大括號包裹。但這4部分都不是必須的,即使一個部分都沒有,只要格式正確(如果有下一篇,會解釋這個格式),就會被steam客戶端加載。
詳細(xì)介紹
這里會對上面4部分做詳細(xì)介紹,包括說明。和相關(guān)屬性的默認(rèn)值、可選值怎么使用可以參考入門篇的styles。
需要注意的是,這些屬性在某些地方可能有特殊用法(比如下載進(jìn)度條),在使用特殊用法的地方,v社開發(fā)人員都貼心的留下注釋了,這里我只關(guān)注一般情況。
語法
先了解一下語法,吐槽一下layout文件里邊什么格式都有,強(qiáng)迫癥快要死了。
1.1 符號不敏感
在變量中對 = 不敏感,下面兩段代碼的效果一樣的,不過我建議使用 =。
color1="0 0 0 255"
color1 "0 0 0 255" // 有空格代替等號是允許的
空格不敏感,在空格用作兩個屬性之間的間隔、變量名和變量值的連接時,1個空格和100個空格是一樣的
// 在變量中
// 下面兩種情況效果一樣
color1="0 0 0 255"
color1 = "0 0 0 255"
// 下面兩種情況效果一樣
color1 "0 0 0 255"
color1 "0 0 0 255"
// 在style、control、place、region中,以place為例,其他類似
// 下面兩種情況效果一樣
place{x=50 y=40 width=max} // 在這里對等號敏感
place{ x = 50 y = 40 width = max }
換行不敏感,找不到合適的語言來描述,放代碼自行體會
// 在style、control、place、region中,以place為例,其他類似
// 下面的情況效果一樣
place{x=50 y=40 width=max}
place{
x=50 y=40 width=max
}
place
{x=50 y=40 width=max}
place
{
x=50 y=40 width=max
}
1.2 樣式
在controls、layout 、styles內(nèi)部使用
button {
textcolor="0 0 0 255"
bgcolor="255 255 255 0"
padding=10
}
其中button是名稱,textcolor和bgcolor是屬性"0 0 0 255"和10是屬性值
2 style
定義一個樣式,供control、place、region 使用。
button {
textcolor="0 0 0 255"
bgcolor="255 255 255 0"
}
注意:所有的屬性都不是必須的
2.1 字體相關(guān)
| 屬性 | 類型 | 默認(rèn)值 | 預(yù)設(shè)值 | 說明 |
|---|---|---|---|---|
| font-family | 字符串 | Tahoma | - | 字體名稱 |
| font-size | 整數(shù) | - | - | 字體大小,單位像素 |
| font-weight | 整數(shù) | 400 | 0~1000 | 字體粗細(xì)。400是標(biāo)準(zhǔn),700是粗體 |
| font-style | 字符串 | normal | normal(正常),italic(斜體),underline(下劃線),strikeout(刪除線),uppercase(大寫),lowercase(小寫),symbol,antialias,dropshadow,outline,rotary,additive | 字體樣式,其中一些可以疊加 |
-
字體樣式:
- normal(正常)
normal(正常)- italic(斜體)
italic(斜體)- underline(下劃線)
underline(下劃線)- strikeout(刪除線)
strikeout(刪除線)- uppercase(大寫)
image.png- lowercase(小寫)
image.png- symbol(未知)
image.png- antialias(未知)
image.png- dropshadow(未知)
image.png- outline(未知)
image.png- rotary(未知)
image.png- additive(未知)
image.png
2.2 顏色相關(guān)
| 屬性 | 類型 | 說明 |
|---|---|---|
| bgcolor | 字符串或顏色 | 背景色 |
| textcolor | 字符串顏色 | 文字顏色 |
| selectedtextcolor | 字符串顏色 | 選中文字顏色 |
| selectedbgcolor | 字符串顏色 | 選中文字背景色 |
| shadowtextcolor | 字符串顏色 | 在不同的控件中有不同的意義 |
2.3 布局相關(guān)
| 屬性 | 類型 | 默認(rèn)值 | 說明 |
|---|---|---|---|
| padding | 整數(shù) | 0 | 內(nèi)邊距,只是用與類型為Label或Button的control |
| insert | 整數(shù) | "0 0 0 0" | 子控件在控件中如何定位,4個數(shù)字分別代表距離左、上、右、下的距離,對bgcolor起作用 |
| minimum-width | 整數(shù) | 0 | 最小寬度,不適用與所有控件 |
| minimum-height | 整數(shù) | 0 | 最小高度,不適用與所有控件 |
- padding(內(nèi)邊距)
padding=30

假如紫框?yàn)槎x的控件,綠框+紫框就是實(shí)際顯然效果的效果,當(dāng)然顏色還是原來定義的顏色,這里只是方便區(qū)分
padding-left=30
padding-top=30
padding-right=30
padding-bottom=30
這段代碼和上面那段可以達(dá)到一樣的效果
- insert
insert="30 30 30 30"

假如綠框是定義的控件,紫框就是加上上面代碼后的效果,顯示不全的部分會被隱藏
insert-left=30
insert-top=30
insert-right=30
insert-bottom=30
這段代碼和上面那段可以達(dá)到一樣的效果
2.4 image
用圖片替代文字,使用于Label和Button控件(控件類型屬于control部分內(nèi)容)
image="graphics/broadcast/icon_close_default"
值為一個圖片的相對于皮膚文件夾根目錄的相對位置,不要帶文件后綴。當(dāng)然這里的圖片指的是tag格式的圖片
2.5 render、render_bg(渲染)
這兩個屬性都是用于渲染的,前者在控件繪制之后開始繪制,后者在控件繪制之前開始繪制,說的通俗一點(diǎn)就是前者是繪制遮罩,后者是繪制背景。
做個比喻方便理解,bgcolor是你的皮膚顏色,render_bg是衣服顏色,textcolor衣服上字的顏色,render是圍裙的顏色。
- 注意: render_bg在bgcolor繪制之后繪制,這意味著bgcolor的效果可能被覆蓋。
每一個完整的渲染由一組渲染指令完成(一條指令也能完成一個完整的渲染),每條渲染指令可以指定一種渲染方式,包括fill、image、image_tiled、image_scale、image_proportional、gradient、gradient_horizontal、dashedrect。
無論哪種方式渲染都需要至少4個參數(shù),這4個參數(shù)實(shí)際上是2個坐標(biāo),以控件占據(jù)的區(qū)域?yàn)闇?zhǔn) (x0,y0)表示左上角,(x1,y1)表示右下角,假設(shè)一個控件占據(jù)的區(qū)域長100,寬70,那么有:
// ==兩邊代碼指定的區(qū)域相同
(x0, y0)==(x1-100, y0-70)
(x1, y1)==(x0+100, y0+70)
(x0+20, y0+30)==(x1-80, y1-40)
描述坐標(biāo)參數(shù)時需要遵從先上后下,先左后右的原則:
// 前兩個參數(shù)為第一個點(diǎn),后兩個參數(shù)為第二個點(diǎn)
0="fill(x0, y0, x0, y0+10, red)" // 正確,先上后下
0="fill(x0, y0+10, x0, y0, red)" // 錯誤,先下后上
0="fill(x0, y0, x0+10, y0, red)" // 正確,先左后右
0="fill(x0+10, y0, x0, y0, red)" // 錯誤,先右后左
這要求我們在確定渲染區(qū)域是要選取左上角和右下角來確定渲染區(qū)域,且需要先寫左上角在寫右下角。
觀察上面的指令,每條指令前面都有一個數(shù)字先看下官方解釋:
The numbers on each line are just an artifact of our common parsing library; it doesn't matter what you put there, and it can all be the same.
大概意思是:每條指令上的數(shù)字只是我們公共解析庫中的一部分;他們并不重要,甚至完全一樣也沒問題。
- 注意:這里我特意引用了官方文檔,其原因是我在制作皮膚的過程中發(fā)現(xiàn):在某些控件中,將渲染指令中的數(shù)字使用一樣的,會導(dǎo)致渲染效果達(dá)不到預(yù)期。當(dāng)我將數(shù)字替換為成不一樣的之后。渲染和我預(yù)期的一樣。
現(xiàn)在來詳細(xì)解釋下這些渲染方式:
- 注意:前4個坐標(biāo)參數(shù)為必須,下表中就不在列舉
2.5.1 fill(填充)
必要參數(shù)
一個顏色,必須是一個定義好的顏色變量-
例子
0="fill(x0, y0, x0+10, y0, red)" 說明
單色填充所選區(qū)域
2.5.2 dashedrect(虛線框)
必要參數(shù)
一個顏色,必須是一個定義好的顏色變量-
例子
0="dashedrect(x0, y0, x0+10, y0, red)" 說明
繪制具有指定顏色的虛線矩形
2.5.3 gradient_horizontal(縱向漸變填充)
必要參數(shù)
使用兩個顏色漸變填充指定區(qū)域,漸變有上到下,第一個顏色為開始漸變,第一個為結(jié)束漸變顏色-
例子
0="gradient_horizontal(x0, y0, x0+10, y0, red, blue)" 說明
漸變填充區(qū)域,方向從上到下
2.5.4 gradient_horizontal(橫向漸變填充)
必要參數(shù)
使用兩個顏色漸變填充指定區(qū)域,漸變有上到下,第一個顏色為開始漸變,第一個為結(jié)束漸變顏色-
例子
0="gradient_horizontal(x0, y0, x0+10, y0, red, blue)" 說明
漸變填充區(qū)域,方向從左到右
2.5.5 image(圖片)
必要參數(shù)
一個圖片的相對于皮膚文件夾根目錄的相對位置,不要帶文件后綴。當(dāng)然這里的圖片指的是tag格式的圖片,與image屬性一樣-
例子
0="image(x0, y0, x0+10, y0, graphics/broadcast/icon_close_default)" 說明
使用圖片渲染指定區(qū)域,需要注意的是,如果圖片的尺寸不渲染區(qū)域要大,可能圖片會超出指定的渲染區(qū)域
2.5.6 image_tiled(圖片,拓展)
必要參數(shù)
同上-
例子
0="image_tiled(x0, y0, x0+10, y0, graphics/broadcast/icon_close_default)" 說明
從指定區(qū)域的左上角開始,重復(fù)渲染該圖片,直到鋪滿整個區(qū)域。
假設(shè)你現(xiàn)在新建一個文本文檔,你的指定你的記事本區(qū)域?yàn)殇秩緟^(qū)域,數(shù)字1為渲染的圖片,使用使用此渲染方式就是不停的按1,直到整個文檔全是1
2.5.7 image_scale(圖片,縮放,不等比例)
必要參數(shù)
同上-
例子
0="image_scale(x0, y0, x0+10, y0, graphics/broadcast/icon_close_default)" 說明
縮放圖片,鋪滿整個區(qū)域,圖片可能會變形
2.5.8 image_proportional
必要參數(shù)
同上-
例子
0="image_proportional(x0, y0, x0+10, y0, graphics/broadcast/icon_close_default)" 說明
縮放圖片,鋪滿整個區(qū)域,會等比例縮放,圖片不會變形
3 control
control在controls區(qū)域內(nèi)被定義,它賦予控件樣式和具體作用
- 注意: 這control部分內(nèi)容并沒有文檔作為支撐,絕大部分內(nèi)容靠我自己腦補(bǔ)的,所以此部分巨大多數(shù)情況下我不建議去調(diào)整。
// 一個樣式
fileimage {
controlname="ImagePanel"
image=resource/icon_file
zpos=1
style="fileimagestyle"
}
其中fileimage為該控件的名稱,用在其他地方引用這個控件,{}內(nèi)的為該控件的屬性
3.1 屬性
屬性|類型|預(yù)設(shè)值|說明
-|-|-|-|-
controlname|string|Label、URLLabel、ImagePanel、Button、CheckButton、RadioButton|控件類型
style|string|-|styles中定義的樣式
恩,沒了(逃)
其他的屬性,根據(jù)屬性名大概能猜出來什么意思,但在實(shí)際使用中,有時有用,有時又沒有用,索性就不說了。
control一般都不去動他,只是用來確定控件使用的style的。
4 layout
4.1 說明
這里的layout并非指.layout文件,而是.layout文件中的layout區(qū)域,這個區(qū)域是用來確定控件的在客戶端上位置的。
在這個區(qū)域中有兩種確定控件位置的方式:region和place,前者多用于指定包含多個控件的一個區(qū)域,后者則用來單獨(dú)指定某個控件的位置,當(dāng)然前者用來單獨(dú)指定一個區(qū)域也是完全沒有問題的。
place和region命令有很多參數(shù),其中絕大部分都是通用的,并且這些參數(shù)全是可選的。
4.2 place和region的屬性(參數(shù))簡要說明
| 屬性 | 類型 | 必須 | 默認(rèn)值 | 預(yù)設(shè)值 | 說明 |
|---|---|---|---|---|---|
| control | 字符串 | 否 | - | - | 為該區(qū)域指定一個control,可以一次指定多個control |
| region | 字符串 | 否 | - | - | 為該區(qū)域指定一個父容器,并且該區(qū)域的相對于父級定位 |
| name | 字符串 | 否 | - | - | 為該區(qū)域指定一個名稱,方便其他區(qū)域應(yīng)用 |
| x | 整數(shù) | 否 | 0 | - | 相對于父容器的絕對定位,原點(diǎn)在父容器的左上角。若沒有指定父容器為.layout文件指定的區(qū)域 |
| y | 整數(shù) | 否 | 0 | - | 同x,x、y構(gòu)成一個坐標(biāo)確定該區(qū)域的左上角 |
| width | 整數(shù) | 否 | - | - | 該區(qū)域的寬度,單位像素,父容器參考x |
| height | 整數(shù) | 否 | - | - | 該區(qū)域的高度,單位像素,父容器參考x |
| start | 字符串 | 否 | - | - | 用來參考定位的其他區(qū)域的名稱 |
| dir | 字符串 | 否 | right | down、right | 相對于參考區(qū)域的方向 |
| align | 字符串 | 否 | top-left | bottom、top、left、right、top-left、top-right | 該區(qū)域的對其方式 |
| margin | 整數(shù) | 否 | 0 | - | 該區(qū)域的外邊距(上下左右),單位像素,可以使用margin-left, margin-right, margin-top, margin-bottom的方式指定單獨(dú)每一邊的邊距 |
| padding | 整數(shù) | 否 | 0 | - | 該區(qū)域的內(nèi)邊距(上下左右),單位像素,可以使用padding-left, padding-right, padding-top, padding-bottom的方式指定單獨(dú)每一邊的邊距 |
| spacing | 整數(shù) | 否 | 0 | - | 區(qū)域中控件的間距,單位像素 |
| overflow | 字符串 | 否 | - | allow-horizo??ntal、allow-vertical、allow-both、scroll-horizo??ntal、scroll-vertical、scroll-both | region獨(dú)有,區(qū)域內(nèi)的內(nèi)容超出該區(qū)域后的處理方式,帶有allow及時內(nèi)容超出,依舊會顯示,并且不會改變定義好的樣式,帶有scroll的內(nèi)容超出后會為該區(qū)域添加一個滾動條 |
4.3 屬性詳細(xì)說明
我會挑出我認(rèn)為不容易理解的屬性,詳細(xì)說明一下
4.3.1 region、place
layout {
// 區(qū)域1
region {
name="aRegion"
width=100
height=200
x=50
y=50
}
// 區(qū)域2
place {
region="aRegion"
width=20
height=20
x=50
y=40
}
// 區(qū)域3
region {
region="aRegion"
width=50
height=100
}
// 區(qū)域4
place {
width=130
height=140
}
}
上面的4個區(qū)域,實(shí)際上不會有任何顯示。只定義了區(qū)域,沒有定義要展示的內(nèi)容。
假如每一個區(qū)域都是有邊框的,他們一定是這樣的:

先看區(qū)域1(黑框):
- 定義了一個名稱為aRegion的矩形區(qū)域,矩形區(qū)域的長為100像素,高為200像素
- 沒有指定region屬性,默認(rèn)父容器為.layout控制的區(qū)域
- 指定x、y,所以從(50,50)出開始渲染
區(qū)域2(綠框):
- 定義一個20 x 20的區(qū)域
- 指定aRegion為父容器
- 指定從(50,40)開始渲染,對于.layout文件就是從(100,90)開始渲染
區(qū)域3(紅框):
- 定義一個50 x 100的區(qū)域
- 指定aRegion為父容器
- 指定從(0,0)開始渲染,對于.layout文件就是從(50,50)開始渲染
先看區(qū)域4(紫框):
- 定義一個130 x 140的區(qū)域
- 沒有指定region屬性,默認(rèn)父容器為.layout控制的區(qū)域
- 指定x、y,所以從(50,50)出開始渲染
4.3.2 control
// 指定單個control
place {
control=DetailsBorder
y=1
x=1
width=max
height=max
}
// 指定多個control
// 使用逗號隔開
place {
control=welcomedetails,rentaldetails,turnnotifications,friendsdetails,achievementsdetails,dlcdetails,clouddetails,communityfilesdetails,newsdetails,nonsteamdetails,screenshotsdetails
region=detailsbody
spacing=30
dir=down
width=max
margin-left=25
}
指定一個或者多個control使用這個區(qū)域
dir
place {
control=welcomedetails,rentaldetails,turnnotifications,friendsdetails,achievementsdetails,dlcdetails,clouddetails,communityfilesdetails,newsdetails,nonsteamdetails,screenshotsdetails
region=detailsbody
spacing=30
dir=down
width=max
margin-left=25
}
在指定多個control時使用dir來指定這些control的排列方式,right水平向右,down垂直向下
spacing
place {
control=welcomedetails,rentaldetails,turnnotifications,friendsdetails,achievementsdetails,dlcdetails,clouddetails,communityfilesdetails,newsdetails,nonsteamdetails,screenshotsdetails
region=detailsbody
spacing=30
dir=down
width=max
margin-left=25
}
在指定多個control時使用dir來指定這些control之間的間隔,單位像素,水平向右
4.3.3 margin(外邊距)
layout {
place {
width=100
height=100
x=10
y=40
margin=30
}
}
圖:

圖中紫色為最終渲染結(jié)果,綠色虛線框僅僅為輔助線,margin為外邊距,即外邊的邊距,只影響實(shí)際渲染的位置,不影響內(nèi)容
margin=10
和
maring-left=10
maring-top=10
maring-right=10
maring-bottom=10
效果相同
4.3.4 padding(外邊距)
這部分和style中的margin一樣
4.3.5 start
place {
control="change_user_button"
align=left
height=24
}
place {
control="account_name_label"
start="change_user_button"
dir="right"
height=24
margin-left=-4
}
start用來給定一個參考,給出的參考是control不是region,start能和dir聯(lián)合使用,指定dir為right或者down來讓當(dāng)前布局生成在參考控件的右邊或者下面。
設(shè)備標(biāo)識符
這個是用來做適配的,隨便找一句
ClientTitle:FrameFocus [!$OSX] {
font-family=basefont
font-size=14
font-weight=400
textcolor="label"
bgcolor="none"
inset="12 6 0 0"
}
ClientTitle:FrameFocus [$OSX] {
font-family=basefont
font-size=15
font-weight=400
textcolor="texthover"
bgcolor="none"
inset="0 6 0 0"
}
第一個適用于非OSX,第二個適用于OSX,其他的基本看到都能明白
結(jié)語
祝,各位玩的愉快~











