1.3.1 SizedBox
自定义组件的尺寸时,较为常见的办法是直接通过SizedBox组件设置其宽度和高度。当该组件的width或height属性不为空时,SizedBox会将其父级约束变为紧约束,以促使SizedBox的child渲染成指定的尺寸,代码如下:
SizedBox( width: 50, height: 50, child: FlutterLogo(), )
运行时可得到一个尺寸为50×50单位的Flutter图标,图略。
没有子组件的SizedBox也很有用。例如,需要在某片区域插入固定大小的留白,就可以直接将SizedBox的尺寸设置为需要的大小,以渲染出一个空白。另外实战中也常借助空白的SizedBox()来满足一个返回Widget类型的函数,有点类似于返回空字符串("")的思路,代码如下:
return_show? FlutterLogo(): const SizedBox();
这样就可以通过_show 变量,在运行时判断是否应显示FlutterLogo组件,或显示一个空白的SizedBox组件。若显示后者,既没有内容,也不占地方,这样就实现了将FlutterLogo隐藏的效果。
Dart Tips语法小贴士
const关键字
细心的读者会发现,上例中SizedBox代码前有一个const关键字。Dart语法里的const关键字表示“编译时常量”,即不需要程序开始运行,就已经可以提前确定好的值。这类值可在编译时确定,且在任何时候都不会改变,因此可以节约少量运行时的性能开支。
在Flutter中,如果一个组件的构造函数所接收的所有参数都为编译时常量,则这个组件本身也可以通过const关键字标注为常量,以小幅提升性能,因此实战中若需要插入留白,则使用const SizedBox()是较为高效的方式。
1.width和height属性
SizedBox组件最常用的功能就是通过width和height属性设置宽度和高度。它们可以接收任意满足父级约束范围内的值,并将自身和子组件尽量设置到相应尺寸。若宽度或高度为空,则SizedBox会直接将父级约束转达给自己的子组件。
如果想要尽量占满全部可用空间,则可以传入double. infinity(正无穷)。例如,可制作一个高度为50单位,但宽度要求占满全屏的Placeholder组件,代码如下:
const SizedBox( width: double. infinity, height: 50, child: Placeholder(), )
运行效果如图1-26所示。
图1-26 宽度占满全屏的Placeholder
由此可见,即使传入的宽度为正无穷,最终SizedBox及Placeholder并没有真的无穷大。这是由于程序自身会被设备的屏幕尺寸所约束。例如某款手机的屏幕宽度为414逻辑像素,则无论怎样用SizedBox或其他办法设置组件的宽度,都无法让组件渲染到屏幕之外,因此若把上例中width属性从正无穷修改为500或415,则在上述设备运行时的效果都是一样的:宽度会被修正为屏幕宽度,即414单位。
为了直观地演示Flutter布局中“尺寸无法违背父级约束”这一原理,这里使用Container、SizedBox和FlutterLogo这3个组件举例,代码如下:
Container( width: 400, height: 400, color: Colors. grey, child: SizedBox( width: 200, height: 200, child: FlutterLogo(), ), )
图1-27 SizedBox所设置的宽度和高度并没有被采纳
上述代码定义了一个400×400单位的灰色Container,内置一个200×200单位的SizedBox,并最后嵌套一个FlutterLogo组件。运行后可观察到一个400×400单位的Flutter徽标,如图1-27所示。
这是因为SizedBox组件所设置的是200×200单位的尺寸,无法满足其父级Container组件要求的400×400单位尺寸,因此被修正为400×400单位,于是FlutterLogo组件最终受到的约束也是400×400单位。由此可见,布局时父级约束的优先级是高于组件本身所设置的尺寸的,过大或过小都会被自动纠正。关于Flutter布局原理,在第6章“进阶布局”中有更详细的介绍。
2.子组件
SizedBox的子组件通过child参数传入。当存在子组件时,SizedBox会尽量约束子组件的尺寸,当子组件不存在时,SizedBox也会将自身尺寸调整到设定的值,占据应有的空间但不绘制任何可见的元素。这一点在实战中非常有用,例如可在Column或Row内插入空白,代码如下:
图1-28 通过SizedBox在Row指定位置插入空白
这里使用了3个FlutterLogo组件,并在第1个与第2个之间插入了一个宽度为20单位的SizedBox组件作为留白,以隔开相邻的两个组件,运行效果如图1-28所示。
上例通过一个宽度不为0的SizedBox组件,实现在Row的指定位置插入留白效果。同理,如需要在Column指定位置插入留白,则应设置SizedBox的高度属性。