1.LayoutElement
这个组件能提供组件的最大最小和最合适大小信息,比如Text,Image都是实现了ILayoutElement接口的组件,所以它会自动获取
如果一个RectTransform的物体的其中一个组件实现了ILayoutElement接口,同时这个RectTransform的物体又添加了Layout Element组件, 那么起作用的是Layout Element
Image继承了ILayoutElement,重写了虚方法,如果没有图片就返回0,如果图片类型是九宫或者重复平铺类型,那么就返回图片的原始大小
2.LayoutGroup
LayoutGroups是用来控制子对象位置的,实现布局,但它不控制自己;当父对象添加了LayoutGroup,那么子对象的位置不再由子对象自己控制
一共有3种组件如下图,网格布局(Grid)、水平布局(Horizontal)、垂直布局(Vertical),一个游戏物体最多只能添加一个LayoutGroup
-
Horizontal & Vertical Layout Group
水平布局和垂直布局都差不多,区别只是一个排列是水平方向,一个是垂直方向,这里选水平方向来介绍.
Padding:内边距,可以设置距离上下左右四个边框的偏移量
Spacing:表示cell之间的距离,也就是整个布局中每个单元之间的距离
Child Alignment:表示对齐方式
Control Child Size:是否控制子物体的大小(新版UGUI水平和垂直布局都添加了这个选项,网格布局依旧自动控制,老版本三个布局组件都默认控制子对象大小)
Child Force Expand:表示自适应 宽 高,勾选上后所有子物体会被拉伸以至填充满整个布局容器
-
Grid Layout Group
Cell Size:子物体大小
Start Corner: 子物体排列的角度
Start Axis: 子物体排列的方向
Constraint: Flexible灵活的( 按照父物体长宽自动横竖行 ) Fixed Column Count 指定列数 Fixed Row Count 指定行数
一般用空物体来作为布局容器(父物体)然后布局容器下就是很多个格子(cell)了,而一个cell下面可能会放很多图片,例如说要有一个格子的背景图片,然后一个物品图片,所以一个cell我们也会用空的gameobject来当父节点。
3.LayoutControl
LayoutControl主要用于控制组件附加物体的RectTransform,ContentSizeFitter就是一个LayoutControl组件,LayoutGroup下的子物体大小已被控制了,会冲突所以添加不了ContentSizeFitter
-
自动布局的实际运用
1.创建一个空物体作为布局容器(父物体),为父物体添加一种布局方式的组件如Grid Layout Group
2.把做好的格子(cell)拖放成Prefab,创建脚本实例化Prefab,把它设置为布局容器的子物体即可(setParent),Layout Group会根据大小自动计算布局,注意这个脚本最好挂在布局容器上
总结
父控件:指的是添加了LayoutGroups组件的GameObject
控件大小信息:指的是控件最小大小,最合适(期望)大小,控件最大大小
1.1 LayoutElement负责提供该组件所附加的物体的控件大小的信息,不提供位置信息。只提供大小信息,并且不直接控制自己的大小,由其它组件控制.例如,LayoutControl、LayoutGroups
1.2Text,Image本身就实现了ILayoutElement接口,提供了控件大小的信息,但它的控件大小信息是系统源码提供的;如果想修改Text,Image等控件大小的信息,可以给物体添加LayoutElement组件,系统会读取LayoutElement组件提供的大小
父对象LayoutGroups是如何利用控件提供的大小信息来控制子对象大小和位置,并分配空间的呢?
首先,父对象获取控件期望的最小的大小,然后分配最小的大小,即使父控件的空间比子控件的期望大小要小,子控件也一样可以获得它期望的最小值,也就是最小的大小一定能够得到满足.
其次,如果父对象还有足够的空间,那就分配控件的最合适(期望)的大小给控件.
最后,如果父控件分配完最合适(期望)大小之后,还有额外空间.则按照控件提供的最大(扩展比率)大小,按照比率分配额外的空间给控件.
最大值,它是一个相对数值,是0和大于0的数组成。该值的意思是表示父控件的多个子控件分配额外空间的一个比率,最大值设置是在Layout Element的Flexible Width和Flexible Height.
举个栗子:比如一个父控件下有A、B两个子控件,A的最大值是1,B的最大值是2,则表示父控件剩余的空间平分三分,A占用1份,B占用2份,0表示不占用父控件的多余空间.
总之,父控件分配子控件的大小是按照先保证子控件满足最小大小的要求;然后,如果父控件还有足够的空间,就分配给子控件按照合适的大小;如果还有额外的空间,则分配给子控件比率空间.
再举个栗子:有A、B两个子控件,A设置宽高最小值为0,0,期望值为0,0,最大值2,2,B设置宽高最小值为0,0,期望值为100,100,最大值1,1,父控件的大小为160×160.
- 第一轮 按照最小值分配给A、B,得到A、B控件的大小都为0,0
- 第二轮 父对象此时空间依然还是160×160,空间足够,按照适合大小进行分配,A适合大小0,0,B适合大小100,100
- 第三轮 分配完父容器还剩余60×60,还有额外空间,则按照A、B设置的最大值平分分配,A最大值2,B最大值1,一共3份,60/3=20,每份20,那么A分到的就是40×40,B分到的就是20×20,加上之前分配的,则A控件大小是40×40,B控件大小120×120,分配完毕.