SOUI2-布局系统

布局系统

每个UI界面都是由大量的界面元素构成的,在window编程中,这些界面元素的最小单位被称为控件,而布局则是这些控件在界面的相对位置和大小。

目前SOUI支持锚点布局、线性布局、网格布局,下面会依次介绍这几种布局方式。

锚点布局

所谓锚点布局,是定义了一个控件的坐标位置,这个位置往往不是一个绝对位置,而是相对于前后兄弟控件、父窗口的位置进行布局,这个位置被称为锚点,当父窗口的大小发生改变时,控件会根据该锚点的位置自动做出调整。

SOUI提供如下属性,用于支持锚点布局,分别是:pos、size、offset、width、height。

pos 属性

pos属性是锚点布局中最重要的一个属性,,可以指定2个值,也可以指定4个值,格式如下:

pos="x,y"  //指定2个值
pos="left,top,right,botton"  //指定4个值

当指定2个值时,代表控件左上角的位置,此时控件的大小将取决于子控件的大小,即该控件的大小将自适应。

当指定4个值时,代表该控件左上角和右下角这两个点的位置,通过这两点,即可确认一个控件的大小。

例如:
<window pos="50,50,100,100" colorbkgnd="#ff0000" /><!--绘制红色控件-->

<window pos="200,200" colorbkgnd="#00ff00">  <!--绘制绿色控件-->
  <window pos="10,10,50,50" colorbkgnd="#0000ff"/>  <!--绘制蓝色控件-->
</window>

这里需要注意的是,pos的第三、四参数并不是指定高度和宽度,而是界面坐标位置,高度、宽度有专门的标识符指定,后面介绍。

观察绿色和蓝色,绿色控件的高度和宽度是50,因为没有指定第三、第四参数,窗口的高度和宽度取决于子控件的大小。如果将蓝色控件删除,绿色窗口则不会展示。在子控件中,子控件是布局位置依赖父控件位置的,子控件的在界面中的位置 = 父控件位置 + 自身位置。

pos标记

pos目前支持7种标记,分别是: “|”、“%”、“[”、“]”、“{”、“}”、“@”

  • “|”:代表参考父控件的中心,如“|-10”代表在父控件的中心向左/上偏移10个像素。
  • “%”:代表在父控件的百分比位置,可以是小数、负数,如“%40”代表在父控件40%的位置,“%-40”则等价于1-40%。
  • “[”:代表相对于一个兄弟控件,当用于1、3参数时,参考前一个兄弟控件右边位置;当用于2、4参数时,参考前一个兄弟控件下边位置。
  • “]”:代表相对于一个兄弟控件,当用于1、3参数时,参考后一个兄弟控件左边位置;当用于2、4参数时,参考后一个兄弟控件上边位置。
  • “{”:代表相对于一个兄弟控件,当用于1、3参数时,参考前一个兄弟控件左边位置;当用于2、4参数时,参考前一个兄弟控件上边位置。
  • “}”:代表相对于一个兄弟控件,当用于1、3参数时,参考后一个兄弟控件右边位置;当用于2、4参数时,参考后一个兄弟控件下边位置。
  • “@”:用于指定窗口的大小,只能出现在pos属性的第3、4参数中,用于标识窗口的高度和宽度,当值为负时,代表自动计算窗口的宽度和高度

注意:

  • “|“, "[" ,"]", "{", "}" 中指定的值可以为正或者为负,值为正时代表向右或者下偏移,值为负时代表向左或者上偏移。
  • 当没有指定上述标识时,pos参数值也可取负值,负值代表参考父控件右边或者下边缩进绝对值位置,如:pos="0,0,-0,-0"代表子控件占满整个父控件,pos="10,10,-20,-20"则代表左边和上边缩进10个像素,右边和下边缩进20个像素。
  • 基于前后布局,理论可能出现循环引用,导致界面布局失败,因此在使用时需要特别注意。

简单例子:

 <!--基于红色窗口,在红色窗口的右上角产生一个黄色窗口-->
 <window pos="}0,]-50,@50,@50" offset="-0.5,-0.5" colorbkgnd="#ffff00" />

 <!--在窗口中间产生一个红色控件-->
 <window pos="|0,|0,@50,@50" offset="-0.5,-0.5" colorbkgnd="#ff0000" />
 <!--在红色窗口的右下角产生一个绿色窗口-->
 <window pos="[0,[0,@50,@50" colorbkgnd="#00ff00" />
 <!--基于绿色窗口,在红色窗口的左下角产生一个蓝色窗口-->
 <window pos="{-100,{-0,@50,@50" colorbkgnd="#0000ff" />
 <!--基于蓝色窗口,在红色窗口的左上角产生一个黑色窗口-->
 <window pos="{0,{-100,@50,@50" colorbkgnd="#000000" />

基于特定兄弟窗口的布局

在上边的用例中,除了红色窗口外,其他窗口的位置都是基于红色窗口来进行布局的,但实际代码布局逻辑却不是基于红色窗口位置来书写的。如果换做其他更加复杂的布局需求,代码将会变得异常复杂,归根结底是因为当前控件只能基于前后兄弟控件的位置布局。实际上,SOUI是支持基于特定窗口的布局。要实现该功能,方法如下:

  1. 被参考的控件必须指定窗口的ID属性(不能通过name属性引用)
  2. 在参考控件的pos属性中,使用 sib.方向@参考ID:偏移值 的方式布局

其中:

  • 方向的取值为:left、right、top、bottom。
  • 参考ID为:被参考窗口的ID值,这也是为什么要求被参考窗口必须指定ID属性。
  • 偏移值:单位为像素,是基于方向的取值。

参考红色窗口实现上图布局:

 <!--参考窗口,需指定id值-->
<window pos="|0,|0,@50,@50" offset="-0.5,-0.5" id="10" colorbkgnd="#ff0000" />
   
<window pos="sib.left@10:-50,sib.top@10:-50,@50,@50" colorbkgnd="#000000" />  <!--左上角-->
<window pos="sib.right@10:0,sib.top@10:-50,@50,@50" colorbkgnd="#00ff00" />   <!--右上角-->
<window pos="sib.left@10:-50,sib.bottom@10:0,@50,@50" colorbkgnd="#0000ff" /> <!--左下角-->
<window pos="sib.right@10:0,sib.bottom@10:0,@50,@50" colorbkgnd="#ffff00" />  <!--右下角-->

size、width、height 属性

size、width、height这三个属性用法比较简单,都是用来指定窗口的大小。其中,size可以指定2个参数,size="width, height"。

width、height的取值有3种:full、-1、非负整数。

  • 当取值为”full“时,代表高度或者宽度占满整个父控件。
  • 当取值为”-1“时,代表根据控件内容自动计算控件大小。
  • 非负整数则代表窗口的指定大小。

在文本控件中,有一个maxWidth属性,用于指定文本内容的大小,其内容宽度不得超过maxWidth给定的宽度。

offset 属性

offset属性包含两个值,用于在确定窗口的位置之后,通过偏移量来最终确定窗口位置。

在前面的用例中,offset="-0.5,-0.5",即代表在确定的位置上,分别向上和向左偏移半个窗口大小单位,从而达到窗口显示在父窗口中间位置。同样,负数是向上或者向左,整数是向下或者向右偏移。

线性布局

SOUI线性目前支持两种线性布局类型:垂直线性布局,水平线性布局。该类型通过 layout 属性指定。

layout 属性

该属性用于指定布局类型,有如下取值:

  • vbox 垂直线性布局。
  • hbox 水平线性布局。

垂直线性布局是在垂直方向上平铺控件;水平线性布局是在水平方向上平铺控件。参考下面例子:

    <window pos="5,[2,-0,-0"  >
      <window layout="vbox" pos="0,0,150,-0" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" colorbkgnd="#ff0000" />
        <window size="100,50" colorbkgnd="#00ff00" />
        <text text="垂直线性布局" />
      </window>

      <window pos="[20,0,-0,150" gravity="center" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" colorbkgnd="#ff0000" />
        <window size="100,50" colorbkgnd="#00ff00" />
        <text text="水平线性布局" />
      </window>
    </window>

gravity 属性

这是一个依赖于当前布局类型的属性,用于指定对齐方式,只能用在容器窗口。

当前布局类型为垂直线性布局时,gravity属性值为:

  • left(默认)
  • center
  • right

当前布局类型为水平线性布局时,gravity属性值为:

  • top(默认)
  • center
  • bottom

例子如下:

<window pos="5,[2,-0,-0"  >
      <window layout="vbox" gravity="right" pos="0,0,150,-0" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" colorbkgnd="#ff0000" />
        <window size="100,50" colorbkgnd="#00ff00" />
        <text text="垂直线性布局" />
      </window>

      <window pos="[20,0,-0,150" layout="hbox" gravity="center" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" colorbkgnd="#ff0000" />
        <window size="100,50" colorbkgnd="#00ff00" />
        <text text="水平线性布局" />
      </window>
</window>

layout_gravity 属性

layout_gravity属性同样是用来指定对齐方式。gravity属性只能用于容器窗口,作用范围是该容器窗口中的所有子控件。而layout_gravity属性则是作用于特定子控件。

当前布局类型为垂直线性布局时,layout_gravity属性值为:

  • left
  • center
  • right

当前布局类型为水平线性布局时,layout_gravity属性值为:

  • top
  • center
  • bottom

例子如下:

 <window pos="5,[2,-0,-0"  >
      <window layout="vbox" gravity="right" pos="0,0,150,-0" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" colorbkgnd="#ff0000" />
        <window size="100,50" layout_gravity="left" colorbkgnd="#00ff00" />
        <text text="垂直线性布局" />
      </window>

      <window pos="[20,0,-0,150" layout="hbox" gravity="center" colorbkgnd="#cccccc">
        <window size="100,50" colorbkgnd="#000000" />
        <window size="100,50" layout_gravity="bottom" colorbkgnd="#ff0000" />
        <window size="100,50" colorbkgnd="#00ff00" />
        <text text="水平线性布局" />
      </window>
 </window>

weight 属性

上面用到的例子中,子控件的大小都是固定的,在窗口大小发生改变时,子控件大小并不会跟着变动。如果需要子控件跟随窗口大小变化做出相应改变,则需使用weight属性。

weight属性的工作原理是:先计算出所有子控件的固定大小,剩下的空间根据weight属性指定的权重,将剩余大小自动分配给对应控件。假设有两个同样大小的控件,第一个控件的weight权重是2,第二个控件的weight权重是1,则第一个控件分配到的大小会是第二个控件分配到的大小的两倍。同样,如果两个控件本身大小不一致,即使权重相同,较大的控件分配到的空间也会多余较小的控件。

<window pos="0,0,-0,@200" layout="hbox" colorbkgnd="#cccccc">
  <button height="50" text="我的文本较长" weight="1" />
  <button height="50" text="文本" weight="1" />
  <button height="50" text="我的权重较大" weight="2" />
  <button height="50" text="文本" />
</window>

extend 属性组

在实际应用中,控件与控件之间的距离往往不是相连的,Soui提供了如下几个属性来设置控件的间距:

  • extend:一次指定四个方向间隔,extend="extend_left,extend_top,extend_right,extend_bottom"
  • extend_left:距左边n个像素
  • extend_top:据上边n个像素
  • extend_right:据右边n个像素 
  • extend_bottom:据下边n个像素

示例如下:

<window layout="vbox" pos="0,0,300,-0" colorbkgnd="#cccccc">
  <window size="100,50" colorbkgnd="#000000" />
  <window size="100,50" extend="50,40,20,30" colorbkgnd="#ff0000" />
  <window size="100,50" extend_bottom="40" colorbkgnd="#00ff00" />
  <text text="垂直线性布局" />
</window>

extend属性组中的取值可以为负数,因此可以出现如下布局:

<window layout="vbox" pos="0,0,300,-0" colorbkgnd="#cccccc">
  <window size="100,50" colorbkgnd="#000000" />
  <window size="100,50" colorbkgnd="#ff0000" />
  <window size="100,50" colorbkgnd="#00ff00" extend_top="-20" extend_bottom="-20" />
  <text text="垂直线性布局" />
</window>

size、width、height属性

线性布局中不允许使用pos属性,如果想指定窗口的大小,需要用到size、width、height属性,有如下取值:

  • 正整数:代表固定大小
  • -1:代表该控件的大小依赖子控件大小
  • -2:代表充满整个父控件

示例如下:

<window pos="0,0,-0,@200" layout="hbox" colorbkgnd="#cccccc">
  <button size="-1,-2" text="我的文本较长" />
  <button text="文本"  />
  <button size="-1,-1" text="文本"  />
  <button size="-2,-2" text="我的文本较长" />
</window>

可以看出,如果不指定size的大小,则默认取size="-1,-1"。

网格布局

在以往的布局中,想要实现行列对齐的布局其实比较复杂的。而网格布局,正是为了解决这一问题诞生的。

想要使用网格布局,需要将layout属性值指定为gridLayout。

layout="gridLayout"

columnCount、rowCount 属性

这两个属性用于指定行列数,rowCount代表行数,columnCount代表列数。

<window pos="5,[3,@350,-10" colorbkgnd="#ff0000" layout="gridLayout" columnCount="2" rowCount="2" xInterval="5" yInterval="5" xGravity="fill" yGravity="fill">
  <button size="50,50" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="50,50" colorbkgnd="#0000000"  text="3" />
  <button size="50,50" colorbkgnd="#0000000"  text="4" />
  <button size="50,50" colorbkgnd="#0000000"  text="5" />
  <button size="50,50" colorbkgnd="#0000000"  text="6" />
  <button size="50,50" colorbkgnd="#0000000"  text="7" />
  <button size="50,50" colorbkgnd="#0000000"  text="8" />
  <button size="50,50" colorbkgnd="#0000000"  text="9" />
</window>

上面布局中,我们指定了行列数均为2,因此会产生一个两行两列的布局。同时,多余的子控件会自动隐藏。并且,可以通过show属性和display属性可以自由控制需要展示的控件。

<button size="50,50" colorbkgnd="#0000000"  text="2" show="0" display="0" />
<button size="50,50" colorbkgnd="#0000000"  text="3" show="0" display="0" />

columnCount、rowCount属性并不需要全部指定,可以只指定其中一个。

<window pos="5,[3,@-1,@-1" colorbkgnd="#ff0000" layout="gridLayout" columnCount="4" xInterval="5" yInterval="5" xGravity="fill" yGravity="fill">
  <button size="50,50" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="50,50" colorbkgnd="#0000000"  text="3" />
  <button size="50,50" colorbkgnd="#0000000"  text="4" />
  <button size="50,50" colorbkgnd="#0000000"  text="5" />
  <button size="50,50" colorbkgnd="#0000000"  text="6" />
  <button size="50,50" colorbkgnd="#0000000"  text="7" />
  <button size="50,50" colorbkgnd="#0000000"  text="8" />
  <button size="50,50" colorbkgnd="#0000000"  text="9" />
</window>

<window pos="5,[30,@-1,@-1" colorbkgnd="#ff0000" layout="gridLayout" rowCount="4" xInterval="5" yInterval="5" xGravity="fill" yGravity="fill">
  <button size="50,50" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="50,50" colorbkgnd="#0000000"  text="3" />
  <button size="50,50" colorbkgnd="#0000000"  text="4" />
  <button size="50,50" colorbkgnd="#0000000"  text="5" />
  <button size="50,50" colorbkgnd="#0000000"  text="6" />
  <button size="50,50" colorbkgnd="#0000000"  text="7" />
  <button size="50,50" colorbkgnd="#0000000"  text="8" />
  <button size="50,50" colorbkgnd="#0000000"  text="9" />
</window>

interval、xInterval、yInterval 属性

该属性用于指定子控件间的间距。

xGravity、yGravity、gravity属性

该属性用于指定行列对齐方式。其中:

  • xGravity指定水平对齐方式,取值为left、center(默认)、right、fill。
  • yGravity指定垂直对齐方式,取值为top、center(默认)、bottom、fill。
  • gravity分别指定水平和垂直对齐方式,可以取left、center、right、top、bottom、fill。其中,left与top是同一值,right与bottom是同一值,当gravity="right"时,默认等价xGravity="right"、yGravity="bottom"。

fill代表子控件大小不受自身大小控制,填充整行或者整列。

例子如下:

<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" xGravity="right" yGravity="bottom" columnCount="2" xInterval="5" yInterval="5"  colorBkgnd="#888888">
  <button size="50,100" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="100,50" colorbkgnd="#0000000"  text="3" />
  <button size="100,50" colorbkgnd="#0000000"  text="4" />
</window>

仅指定gravity值:

<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" gravity="right" columnCount="2" xInterval="5" yInterval="5"  colorBkgnd="#888888">
  <button size="50,100" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="100,50" colorbkgnd="#0000000"  text="3" />
  <button size="100,50" colorbkgnd="#0000000"  text="4" />
</window>

layout_xGravity、layout_yGravity 属性

该属性不能用于容器窗口,只能用在子控件中。

该属性取值和gravity一致。

子控件的layout_xGravity和父控件的xGravity是一个主从关系。优先使用子控件指定的属性,如果子控件没有指定,则使用父窗口的属性。

例子如下:

<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" columnCount="2" xInterval="5" yInterval="5"  colorBkgnd="#888888">
  <button size="50,100" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" colorbkgnd="#0000000"  text="2" />
  <button size="100,50" colorbkgnd="#0000000"  text="3" />
  <button size="100,50" colorbkgnd="#0000000"  text="4" />
</window>

<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" columnCount="2" xInterval="5" yInterval="5"  colorBkgnd="#ff0000">
  <button size="50,100" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" layout_yGravity="bottom" colorbkgnd="#0000000"  text="2" />
  <button size="100,50" colorbkgnd="#0000000"  text="3" />
  <button size="100,50" colorbkgnd="#0000000"  text="4" />
</window>

rowSpan、columnSpan属性

该属性不能用于容器窗口,只能用在子控件中。

用于指定行列合并。rowSpan="2" 即该控件占2行。

例子如下:

<window pos="|0,[5" offset="-0.5,0" layout="gridLayout" columnCount="2" xInterval="5" yInterval="5"  colorBkgnd="#ff0000">
  <button size="50,100" rowSpan="2" colorbkgnd="#0000000"  text="1" />
  <button size="50,50" layout_yGravity="bottom" colorbkgnd="#0000000"  text="2" />
  <button size="100,50" colorbkgnd="#0000000"  text="3" />
  <button size="100,50" colorbkgnd="#0000000"  text="4" />
</window>

rowWeight、columnWeight 属性

该属性不能用于容器窗口,只能用在子控件中。

该属性类似线性布局中weight属性。

posted @ 2024-03-08 10:26  西兰花战士  阅读(77)  评论(0编辑  收藏  举报