窗口的布局
描点布局
SOUI 的锚点布局
SOUI 布局全部采用相对坐标,由 pos,offset(pos2type), size, width,height 这几个个窗
口属性配合指定。
size, width, height 属性
size, width, height 比较简单,是用来指定窗口的大小的,只有在 pos 属性指定的值个数
不为 4 时生效。
size 是 2014 年底增加的布局属性,size="width,height"。
width, height 可以有 3 种值:full,-1,非负整数。
为 full 时,代表高度或者宽度和父窗口的客户区大小相等。
-1 代表根据窗口内容自动计算窗口大小。
非负整数直接指定窗口大小。
在图片控件中,控件是指定的皮肤默认大小。
在文本控件中,还可以指定一个 maxWidth 属性,控件是文本内容的大小,但宽度不超过
maxWidth。
pos 属性
pos 属性可以指定 4 个值,也可以指定 2 个值。指定 4 个值时,分别代表控件的
left,top,right,bottom,指定两个值时代表控件的 x,y,具体位置还依赖于另外 3 个参数。
37
指定 4 个值时,pos 目前支持 7 种标志:|,%,[,],{,},@
“|”代表参考父窗口的中心;如|-10 代表在父窗口的中心向左/上偏移 10 象素。
“%”代表在父窗口的百分比,可以是小数,负数。如:%40 代表在父窗口的 40%位
置,%-40 则等价于(1-40%)。
“[”相对于前一兄弟窗口。用于 X 时,参考前一兄弟窗口的 right,用于 Y 时参考前一兄
弟窗口的 bottom
“]”相对于后一兄弟窗口。用于 X 时,参考后一兄弟的 left,用于 Y 时参考后一兄弟的 top
“{”相对于前一兄弟窗口。用于 X 时,参考前一兄弟窗口的 left,用于 Y 时参考前一兄弟
窗口的 top
“}”相对于后一兄弟窗口。用于 X 时,参考后一兄弟的 right,用于 Y 时参考后一兄弟的
bottom
“@”标志用来指定窗口的大小,只能出现在 pos 属性的第 3,4 个值中,用来标识窗口
的宽度。当后面的值为负时,代表自动计算窗口的宽度或者高度(2015.3.3 新增加解
释)。
注:“|“, "[" ,"]", "{", "}" 中指定的值都可以为正或者负,正时向右或者下偏移,负则向
左或者上偏移。
当没有上述标志时,负号代表参考父窗口的右边或者下边缩进绝对值位置。如:
pos="0,0,-0,-0"代表占满父窗口。而 pos="10,10,-10,-10"则代表在父窗口的基础上向内
全部缩进 10 点。
@:指定窗口的 size。只能用于 x2,y2,用于 x2 时,指定窗口的 width,用于 y2 时指定窗
口的 height。注:只能为正值,负号会自动忽略。
其中“{”和“}”是 SOUI 在 DUIENGINE 的基础上新增加的布局标志(SOUI 是在
DUIENGINE 的基础上全面重构而来)。
注意!!!由于系统运行向前及向后引用,理论上有可能出来循环引用,导致界面布局失败,
因此在使用"[","{",“}” 和"]"这几个标志时需要特别注意。
当 pos 只指定了 x1,y1 时,通常需要和 offset(或者 pos2type),size(或者 width,height)配
合使用。
下面先重点介绍 offset 属性
offset 属性是 SOUI 在通过 pos 属性完成坐标定位后再将坐标进行偏移的属性。和 pos 中
一般使用象素为单位不同,offset 是以控件最后的大小为单位进行平移。
我们可以在 XML 中或者代码中使用 offset = "-0.5,-0.5"这样的形式来描述窗口的坐标平
移属性。
属性中包含两个值,分别对应 X,Y 方向的平移相对于窗口大小的倍数,一般为[-1,0]的小
数(float),当然也可以超过这个范围。
我们先看一下代码中如何实现:
class SOUI_EXP SwndLayout
{
public:
//...
float fOffsetX,fOffsetY; /**< 窗口坐标偏移量, x += fOffsetX *
//...
};
int SwndLayout::CalcPosition(LPRECT lpRcContainer,CRect &rcWindow )
{
int nRet=0;
//...
if(nRet==0)
{//没有坐标等待计算了
rcWindow.NormalizeRect();
//处理窗口的偏移(offset)属性
CSize sz = rcWindow.Size();
CPoint ptOffset;
ptOffset.x = (LONG)(sz.cx * fOffsetX);
ptOffset.y = (LONG)(sz.cy * fOffsetY);
rcWindow.OffsetRect(ptOffset);
}
return nRet;
}
SwndLayout::CalcPosition 是 SOUI 用来通过 pos 及 offset 属性计算窗口坐标的关键函
数,为了突出重点,具体的坐标计算省略了,只列出平移处理部分的代码。
可以看出,在平移处理前,首先获得窗口的 Size,再将 Size 分别乘以 fOffsetX,fOffsetY 这
两个平移系数获得在 x,y 两个方向上的平移量。
最后才是将矩形做平移处理。
注意:pos2type属性已弃用,不要去使用。
线性布局
SOUI 2.5.1.1 开始支持线性布局(LinearLayout).
要在 SOUI 布局中使用线性布局, 需要在布局容器窗口里指定布局类型为 vbox | hbox,
(vbox 为垂直线性布局, hbox 为水平线性布局).
在指定布局类型后还可以为容器窗口指定 gravity 属性, 用来指定子窗口的默认排列模式.
vbox 的 gravity 有:left(默认), center, right。
hbox 有: top(默认), center, bottom。
在线性布局中的子窗口 pos 属性没有意义, 一般直接指定 size="width,height",
width/height 值: -1 代表 wrap_content, -2 代表 match_parent
可以使用 layout_gravity 可以更改当前窗口的排列模式.
使用 extend="left,top,right,bottom", extend_left, extend_top, extend_right,
extend_bottom 来指定间距. (相当于 android 的 margin)
子窗口支持使用 weight 属性.
<!--这里演示在SOUI中使用线性布局,在window中指定layout="vbox,hbox,linearLayout"时窗口的子窗口布局变成自动布局模式-->
<window layout="vbox" size="-1,-1" colorBkgnd="#cccccc" gravity="center">
<!--线性布局的自适应子窗口大小-->
<text>vbox + gravity + wrapContent</text>
<window size="100,30" colorBkgnd="#ff0000" />
<window size="200,30" extend="10,5,10,5" colorBkgnd="#ff0000" />
<window size="120,30" layout_gravity="right" colorBkgnd="#ff0000" />
</window>
<window pos="0,[5,@-1,@200" layout="vbox" colorBkgnd="#cccccc">
<!--线性布局的weight属性-->
<text extend_bottom="10">vbox + gravity + weight</text>
<window size="100,30" colorBkgnd="#ff0000" />
<window size="200,30" extend="10,5,10,5" colorBkgnd="#ff0000" weight="1" />
<window size="120,30" layout_gravity="right" colorBkgnd="#ff0000" weight="1" />
<button size="100,30" extend_top="10">button test</button>
</window>
<window pos="0,[5" layout="vbox" colorBkgnd="#cccccc" id="10000">
<text extend_bottom="10" layout_gravity="center">hbox demo</text>
<window size="-1,-1" layout="hbox" colorBkgnd="#888888">
<!--线性布局之hbox-->
<button size="100,30">button1</button>
<button size="100,30" extend_left="10">button2</button>
<button size="100,30" extend_left="10">button3</button>
<button size="100,30" extend_left="10">button4</button>
</window>
<button size="-1,-1" padding="10,5,10,5" name="btn_open_wrap_content" extend_top="10">打开自适应大小窗口</button>
</window>
1.演示按钮如何居中
<window size="-2,30" layout="hbox">
<window size="0,30" weight="1"/>
<button name="btnUp" size="50,28" extend_left="5">向上</button>
<button name="btnDown" size="50,28" extend_left="5">向下</button>
<window size="0,30" weight="1"/>
</window>
解析:<window size="0,30" weight="1"/>在窗口中相当于一个可变大小的弹簧作用,在上述中两个弹簧始终在窗口的上下,所以可以让两个按钮始终处于中间状态。
- layout="hbox"时属性gravity="center" 是让窗口中的控件垂直居中.
- <window size="-2,-1" layout="hbox" gravity="center" >必须是这个格式的时候,size="0,-2" weight="1"这两个属性配合才有效。如果是<window layout="hbox" >这种格式虽然窗口的布局也是水平布局,但不能实现size="0,-2" weight="1"两个属性。
- <window size="0,-2" weight="1" layout="vbox" gravity="center" extend="5,0,5,0">中gravity="center"这个属性,对<text size="-2,-1" text="" colorText="RGB(0,0,255)"/>不起作用,原因是使用了size="-2,-1",若要起作用则改成size="70,28"。
网格布局
<window pos="10,[5,@350,-10" layout="gridLayout" columnCount="4" rowCount="6" xInterval="5" yInterval="5" xGravity="fill" yGravity="fill">
<edit size="0,0" cueText="数值" columnSpan="4" rowWeight="2" colorBkgnd="#ffffe0ff" />
<button size="0,0" text="清除" columnWeight="1" rowWeight="1" colorText="#0000ff" animate="1"/>
<button size="0,0" text="后退" columnWeight="1" rowWeight="1" animate="1"/>
<button size="0,0" text="/" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="x" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="7" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="8" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="9" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="-" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="4" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="5" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="6" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="+" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="1" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="2" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="3" columnWeight="1" rowWeight="1" animate="1" />
<!--//列 行权重为1-->
<button size="0,0" text="=" rowSpan="2" columnWeight="1" rowWeight="2" animate="1" />
<button size="0,0" text="0" columnSpan="2" columnWeight="2" rowWeight="1" animate="1" />
<!--跨两列 自动填充 列权重2 行权重1-->
<button size="0,0" text="." columnWeight="1" rowWeight="1" animate="1" />
<!--列 行 权重1-->
</window>
- 网格布局的疑问在于size的大小不能设定。
<window size="-2,110" extend_left="2" layout="gridLayout" columnCount="7" rowCount="4"
xInterval="5" yInterval="11" xGravity="fill" yGravity="fill" margin="1,1,1,1" colorBorder="#ff000000">
<check size="28,18" id="1800" focusable="0"/>
<check size="28,18" id="1801" focusable="0"/>
<check size="28,18" id="1802" focusable="0"/>
<check size="28,18" id="1803" focusable="0"/>
<check size="28,18" id="1804" focusable="0"/>
<check size="28,18" id="1805" focusable="0"/>
<check size="28,18" id="1806" focusable="0"/>
<check size="28,18" id="1808" focusable="0"/>
<check size="28,18" id="1809" focusable="0"/>
<check size="28,18" id="1810" focusable="0"/>
<check size="28,18" id="1811" focusable="0"/>
<check size="28,18" id="1812" focusable="0"/>
<check size="28,18" id="1813" focusable="0"/>
<check size="28,18" id="1814" focusable="0"/>
<check size="28,18" id="1816" focusable="0"/>
<check size="28,18" id="1817" focusable="0"/>
<check size="28,18" id="1818" focusable="0"/>
<check size="28,18" id="1819" focusable="0"/>
<check size="28,18" id="1820" focusable="0"/>
<check size="28,18" id="1821" focusable="0"/>
<check size="28,18" id="1822" focusable="0"/>
<check size="28,18" id="1824" focusable="0"/>
<check size="28,18" id="1825" focusable="0"/>
<check size="28,18" id="1826" focusable="0"/>
<check size="28,18" id="1827" focusable="0"/>
<check size="28,18" id="1828" focusable="0"/>
<check size="28,18" id="1829" focusable="0"/>
<check size="28,18" id="1830" focusable="0"/>
</window>
行列对齐
<text pos="|0,10" offset="-0.5,0" text="行列对齐" />
<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" columnCount="2" xInterval="5" yInterval="5" xGravity="right" colorBkgnd="#888888">
<text size="-1,-1">所在地:</text>
<edit size="200,50" layout_xGravity="fill">广东 广州</edit>
<text size="-1,-1">邮箱:</text>
<edit size="200,-1" layout_xGravity="fill">xx@qq.com</edit>
<text size="-1,-1">兴趣:</text>
<edit size="200,-1" layout_xGravity="fill">看小电影</edit>
</window>
三分窗口
<window size="-2,-2" layout="gridLayout" columnCount="2" xGravity="fill" yGravity="fill">
<window size="0,0" rowSpan="2" columnWeight="1" colorBkgnd="#ff0000" />
<window size="0,0" columnWeight="1" rowWeight="1" colorBkgnd="#00ff00" />
<window size="0,0" columnWeight="1" rowWeight="1" colorBkgnd="#0000ff" />
</window>
root大小自动计算
<!--演示root大小自动计算,注意soui结点width,height的设置,哪一个值需要自动计算就设置为-1-->
<root size="-2,-1" layout="vbox" padding="5,5,5,5" colorBkgnd="#ffffff">
<caption size="-2,-1" colorBkgnd="#ffff00">
<text size="-1,-1" font="bold:1" text="窗口大小自适应演示,支持左右拉伸"/>
</caption>
<window size="-2,100" layout="hbox">
<window size="0,-2" text="水平平分窗口1" weight="1" colorBkgnd="#ff0000"/>
<window size="0,-2" text="水平平分窗口2" weight="1" colorBkgnd="#00ff00"/>
<window size="0,-2" text="水平平分窗口3" weight="1" colorBkgnd="#0000ff"/>
</window>
<text size="-1,-1" text="使用layout_gravity属性居中对齐" layout_gravity="center"/>
<window size="-1,-1" layout_gravity="right" extend_top="5" layout="hbox">
<!--IDCANCEL支持enter退出窗口-->
<button size="-1,-1" padding="10,5,10,5" id="IDOK" text="确定"/>
<!--IDCANCEL支持esc退出窗口-->
<button size="-1,-1" padding="10,5,10,5" extend_left="10" id="IDCANCEL" text="取消"/>
</window>
</root>