布局元素与布局控制器
布局元素实现ILayoutElement接口,布局控制器实现ILayoutController接口,后者根据前者的属性控制具体布局——有些布局控制器也是布局元素,即同时实现这两个接口,如LayoutGroup。
public interface ILayoutElement
{
float minWidth { get; }
float minHeight { get; }
float preferredWidth { get; }
float preferredHeight{ get; }
float flexibleWidth { get; }
float flexibleHeight { get; }
int layoutPriority { get; }
// 自下而上计算宽度,先计算子元素,再计算父元素
void CalculateLayoutInputHorizontal();
// 自下而上计算高度,先计算子元素,再计算父元素
void CalculateLayoutInputVertical ();
}
public interface ILayoutController
{
// 自上而下计算宽度
void SetLayoutHorizontal();
// 自上而下计算高度
void SetLayoutVertical ();
}
注意,布局控制器,可以控制子布局元素,也可以控制同一个GameObject下的布局元素,相当于控制自己的布局,同时它也可以被别的布局控制器所控制,形成嵌套控制。
布局控制器会自动接管,RectTransform的一些属性设置,导致其为不可编辑的灰色状态。
LayoutElement
覆盖布局元素的属性,结合布局控制器,才能生效,比如:HorizontalLayoutGroup。
- 首先,尽量分配 Min 的空间。
- 其次,有多余空间,分配 Preferred 的空间。
- 最后,还有空间,就分配 Flexible 的空间。
其中,Min 和 Preferred 是绝对数值, Flexible是同级元素的比例,即:按照同级元素的Flexible的比例,去灵活分配多余的空间。
例如,两个Button的Flexible:
- 如果是1 : 1,就是多余空间每个1 / 2,然后加到Preferred的尺寸上;
- 如果是1 : 3,就是多余空间每个1 / 4与3 / 4,然后加到Preferred的尺寸上;
- 如果是1 : 0.5,就是多余空间每个2 / 3与1 / 3,然后加到Preferred的尺寸上;
- 如果是0 : 0,就相当于取消Flexible。
注意,容器的Control Child Size需要勾选上,子元素的Layout Element的才能其作用。
ContentSizeFitter
控制启用Min或Preferred尺寸,可以结合Layout Element同级使用,来生效Layout Element的设定。
注意,它生效的时候,如果尺寸变动,会根据pivot来改变伸缩方向,即:pivot在中心就是四圈伸展或收缩,pivot在左上就是向右下伸或收缩,以此类推。
AspectRatioFitter
这东西和Content Size Fitter一样使用,只不过是控制布局元素的“宽高比”,同样也是根据pivot来改变伸缩方向——但不使用布局元素的Min或Preferred尺寸。
Width Controls Height:宽度不变,比率改变高度,比率越小越高,比率越大越低。
Height Controls Width:高度不变,比率改变宽度,比率越小越窄,比率越大越宽。
Fit In Parent:不超越父容器(适应父容器),小于1高度不变,比率越小越窄,大于1宽度不变,越小越低。
Envelope Parent:超越父容器(封装父容器),小于1宽度不变,比率越小越高,大于1高度不变,越大越宽。
GridLayoutGroup
网格布局组,其元素可以自动排列,但本身width和height无法自适应,这会造成内部元素的越界或留白,这时候结合ContentSizeFitter同级约束——就可以实现网格布局,随着内部元素的多少自动适应,即:
将GridLayoutGroup的Constraint设置为Flexible,同时将ContentSizeFitter的Horizontal和Vertical都设置为Preferred。
当然,也可以将GridLayoutGroup的Constraint设置为Fixed Row / Column,即固定行或列,这样结合ContentSizeFitter的Preferred,就可以让行或列自适应——否则,变动行或列的数量,会出现内部元素越界或留白的情况,此时可以用Child Alignment来对齐元素整体的位置,以及遮罩隐藏越界的部分。
另外,Start Corner属性是,第一个元素放在四角的哪一个,然后按照横向或纵向(Start Axis),依照顺序渐次排列填充——只有多行多列才能看出来效果。
可见,Child Alignment是对齐位置(在有多余空间的时候),Start Corner则是填充位置。