UGUI之布局系统学习
文章目录
1. RectTransform自适应布局
每个 Canvas 的子物体都有一个 RectTransform 组件(继承 Transform),它定义了节点的锚点、轴心点的位置、宽高、旋转、缩放等属性。主要用于控制布局和对齐方式。
1.1 轴心点(Pivot):
-
以物体本身为坐标系,左下角为坐标原点(0,0),右上角(1,1)。
-
轴心点是物体旋转和缩放的参照点。
-
当物体宽高改变时,Pivot点决定了物体如何向两边延伸。
比如Pivot点(0.4,0.8)表示当前UI的中心点在宽度40%和高度80%的位置。当你试图将物体的宽扩大 Δx 时,Δx中有40%的部分被分配在了pivot的左边,剩下的部分被分配在了pivot点的右边。
当你需要动态扩展一个UI时,比如一个文本框,你希望文本框的宽度能够根据文本占据的像素动态扩展,同时 此时文本是水平居左对齐,那你需要将pivot点设置在UI的左边框上,即pivot.x= 0,这样当文本框的宽度变大时,它只会向右扩展,而不是向两边扩展。对物体进行缩放时同理。
-
轴心点和锚点共同影响面板上的一组值,这组值会由于锚点的设置不同(即布局方式不同)而显示不同的名称(PosZ通常不会变化)
锚点的位置(布局方式)和这组数值共同决定了物体相对于父物体的布局。
无论父节点大小如何改变,只要布局方式不变,这组数值是维持不变的。
当父节点大小改变时,子物体为了维持这组数值不变,相对于父物体的位置和宽高就会随之改变。
1.2 锚点(Anchors):
锚点决定了当父物体大小发生改变的时候,UI的位置和大小如何变化。
- 每个RectTransform有 Min,Max两个锚点。
- 锚点是归一化的二维向量,以父物体为坐标系,左下角为坐标原点(0,0),右上角(1,1)。
- 两个锚点可以确定一条对角线,即有一个锚框的概念。根据两个锚点的位置,有三种情况:
(1)两个锚点重合,即X,Y都相同,锚框退化为点。
这组值显示为:PosX、PosY:物体的轴心点相对于锚点的位置;Width、Height:物体的宽和高
这种情况下称为绝对布局。绝对布局下,父物体大小改变,子物体大小不会改变。为了保持轴心点与锚点的相对位置,子物体的位置会发生改变。
(2)两个锚点在同一水平线或同一竖直线上,即X,Y有一组相同,锚框退化成一条锚线。
例如:Min(0,1)Max(1,1),即锚框退化成了父节点的上边界。
这组值显示为:Left、Right:物体的左右边界距离左右锚点的水平距离;PosY:物体的轴心点与锚线的垂直距离;Height:物体的高度
这种情况下,当父物体宽度被拉伸时,为了保持物体的左右边界与左右锚点的水平距离不变,子物体也会被拉伸;当父物体高度被拉伸时,为了保持物体的轴心点与锚点的垂直距离不变,子物体就会显得比较靠上,但是高度不会被拉伸。
其他锚线情况类似。
(3)两个锚点X,Y互不相同,形成一个矩形锚框。
这组值显示为:Left、Right、Top、Bottom:表示物体的四条边界与锚框的四条边的距离。
这种情况下,只要父物体大小改变,子物体就会被拉伸。
1.3 anchorMin,anchorMax,offsetMin,offsetMax,sizeDelta,anchoredPosition
anchorMin,anchorMax:归一化的锚点向量。
offsetMin,offsetMax:代表从两个锚点指向物体左下角和右上角的两个向量。offsetmin表示的是当前物体的左下角相对anchorMin锚点的偏移,offsetmax表示的是当前物体的右上角相对anchorMax锚点的偏移。
sizeDelta:尺寸变化量,该属性表示offsetMax - offsetMin得到的向量。绝对布局下即从图片的左下角指向右上角的向量。
由于 rectTransform.rect 是只读的,绝对布局下可以通过修改 sizeDelta 的值来直接改变物体的宽高。相对布局则通过修改offsetMin和offsetMax的值更好理解。
anchoredPosition:下图箭头所代表的向量。
绝对布局下可以直接用来设置子物体的位置。
说明:绿框:子节点;红框:父节点;轴心:Pivot,上图中的箭头指向的蓝色小圈圈;锚点区:AnchoredMin和AnchoredMax构成的一个方框,上图中四个白色小三角构成的区域;虚拟轴心:以子节点的pivot参数在锚点区映射出来的点。示意代码:
float virtualX = Mathf.Lerp(rect.anchorMin.x, rect.anchorMax.x, rect.pivot.x);
float virtualY = Mathf.Lerp(rect.anchorMin.y, rect.anchorMax.y, rect.pivot.y);
Vector2 virtualPivot = new Vector2(virtualX, virtualY);
Vector2 localPosition2D = new Vector2(rect.localPosition.x, rect.localPosition.y);
Vector2 anchoredPosition = localPosition2D - Vector2.Scale(parent.rect.size, visualPivot - Vector2.one * 0.5f);
1.4 常见API用法:
改变RectTransform的top
GetComponent().offsetMax = new Vector2(GetComponent().offsetMax.x, top);
改变RectTransform的Right
GetComponent().offsetMax = new Vector2(right,GetComponent().offsetMax.y);
改变RectTransform的bottom
GetComponent().offsetMin = new Vector2(GetComponent().offsetMin.x, bottom);
改变RectTransform的left
GetComponent().offsetMin = new Vector2(left,GetComponent().offsetMin.y);
改变RectTransform的width,height
GetComponent().sizeDelta = new Vector2(width, height);
改变RectTransform的anchoredPosition
GetComponent().anchoredPosition3D = new Vector3(posx,posy,posz);
GetComponent().anchoredPosition = new Vector2(posx,posy);
void GetLocalCorners(Vector3[] fourCornersArray);
该方法表示获取UI的四个角在以自身Pivot为原点的坐标系中的坐标。作为参数的Vector3数组需要自己声明。获取四个角的顺序是左下、左上、右上、右下。
void GetWorldCorners(Vector3[] fourCornersArray);
该方法表示获取UI的四个角在世界坐标系的坐标。
void SetSizeWithCurrentAnchors(RectTransform.Axis axis,float size);
按照当前的anchor信息来设置尺寸(实际上根据的是pivot,设置的结果与anchor无关),有两个参数,第一个是Axis类型的值,需要指定一个方向,水平或垂直;第二个参数,是本身的宽高。
例:将宽高设为(100,30)。
RectTransform rt = GetComponent();
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal,100);
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,30);
void SetInsetAndSizeFromParentEdge(RectTransform.Edge edge,float inset,float size);
设置当前UI相对父UI边的距离及当前UI的尺寸,第一个参数是一个Edge类型的值,需要指定以父对象的哪个边为基准(也就是Top、Bottom、Left、Right四个值之中的一个,即对齐方式); 第二个参数,是离指定边的距离; 第三个参数,是本身的宽度或者高度。
例:将宽高设为(100,30),与父UI的右边间距为0,与底边间距为0。
RectTransform rt = GetComponent();
rt.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right, 0, 100);
rt.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom, 0, 30);
2.布局组件:Vertical Layout Group、Horizontal Layout Group 和 Grid Layout Group
Vertical Layout Group 垂直布局组:
Padding:与父物体的边的间距(配合对齐方式调整)
Spacing:子物体的间距
Child Alignment:对齐方式
Reverse Arrangeme:反向排列
Control Child Size:是否控制其子布局元素的宽度和高度
Use Child Scale:是否使用子元素缩放后的大小进行布局
Child Force Expand:是否强制子布局元素扩展以填充其他可用空间。
Horizontal Layout Group 水平布局组用法相似。
Grid Layout Group 网格布局组:
Constraint:约束行数或者列数
通常搭配 Content Size Fitter组件使用,使父元素大小自适应。
Content Size Fitter 内容自适应组件:
使父元素大小根据子物体的布局进行大小自适应
LayoutElement 布局元素:
https://docs.unity3d.com/2021.3/Documentation/Manual/script-LayoutElement.html
布局组件的子元素或内容自适应组件上可以挂载 LayoutElement,用来对宽高进行限制。
Ignore Layout:勾选可以让父 layout 忽略该子元素的布局
MinSize:优先保证子元素占据该大小
PreSize:在确保子元素占据MinSize后,会将剩余空间分配给PreSize
FlexSize:如果分配完PreSize还有剩余空间,将空间按比例分配给FlexSize
Layout Priority: 布局优先级;布局系统将使用布局优先级最高的组件的属性值