我要实现的目标类似于GridLayout技术。在Grid Layout中有一个Constraint-Fixed Coloumn Count选项,我将该值设置为2.Grid布局的问题是,当我们将像元大小设置为一个特定的值之后,单元格的大小将不会扩展到所有其他屏幕大小,因此尝试仅用两个列手动设置HorizontalGroup Layout,问题就在于当我需要实例化许多项目时,它应该以顺序1排列第一行2个项目,第二行3,4个项目,依此类推。 我在Gridview上尝试过的一个在Link
中给出答案 0 :(得分:2)
我使用HorizontalLayoutGroup
,VerticalLayoutGroup
和简单的StayQuadratic
的组合来做到这一点,目的是使项目的宽度保持二次方。
public class StayQuadratic : MonoBehaviour
{
private RectTransform rectTransform;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
}
private void Update()
{
rectTransform.sizeDelta = Vector2.one * rectTransform.rect.width;
}
}
当然,只设置一次此大小就足够了,因为您不会在构建中动态更改屏幕大小。
根对象需要VerticalLayoutGroup
宽度
和一个ContentSizeFitter
(仅用于扩展底部的背景,或者用于滚动时使用)
它将附加行。一行需要HorizontalLayoutGroup
和
StayQuadratic
控制)我制作了以下脚本进行设置。对于此示例,我只生成所有对象和项目,但是您当然也可以使用具有相同设置的预制件。
[RequireComponent(typeof(ContentSizeFitter), typeof(VerticalLayoutGroup))]
public class GridWith2Columns : MonoBehaviour
{
public Sprite sprite;
private HorizontalLayoutGroup _currentRow;
private GameObject placeholder;
private int itemCounter;
private void Awake()
{
var verticle = GetComponent<VerticalLayoutGroup>() ? GetComponent<VerticalLayoutGroup>() : gameObject.AddComponent<VerticalLayoutGroup>();
verticle.childAlignment = TextAnchor.UpperCenter;
verticle.childControlHeight = true;
verticle.childControlWidth = true;
verticle.childForceExpandHeight = true;
verticle.childForceExpandWidth = true;
var sizeFitter = GetComponent<ContentSizeFitter>() ? GetComponent<ContentSizeFitter>() : gameObject.AddComponent<ContentSizeFitter>();
sizeFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
sizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
}
public void AddChild()
{
// if exists remove placeholder
if (placeholder)
{
if (Application.isPlaying) Destroy(placeholder);
else DestroyImmediate(placeholder);
}
// Every second item we add a new horizontal row
// starting with the first ;)
if (itemCounter % 2 == 0)
{
var newRowObj = new GameObject("row", typeof(RectTransform), typeof(HorizontalLayoutGroup));
newRowObj.transform.SetParent(transform, false);
_currentRow = newRowObj.GetComponent<HorizontalLayoutGroup>();
_currentRow.childAlignment = TextAnchor.UpperCenter;
_currentRow.childControlHeight = false;
_currentRow.childControlWidth = true;
_currentRow.childForceExpandHeight = true;
_currentRow.childForceExpandWidth = true;
}
// Add a new item child to the current
// I use some example settings like sprite and color just to show how it works
// you can ofcourse also simply instantiate a prefab
var newItem = new GameObject("item", typeof(RectTransform), typeof(Image), typeof(StayQuadratic));
newItem.transform.SetParent(_currentRow.transform, false);
var itemImage = newItem.GetComponent<Image>();
itemImage.color = Color.red;
itemImage.sprite = sprite;
newItem.GetComponent<RectTransform>().sizeDelta = Vector2.one * _currentRow.GetComponent<RectTransform>().rect.width / 2;
itemCounter++;
// add an invisble filler in case of impair child count
if (itemCounter % 2 != 0)
{
placeholder = new GameObject("placeholder", typeof(RectTransform), typeof(StayQuadratic));
placeholder.transform.SetParent(_currentRow.transform, false);
placeholder.GetComponent<RectTransform>().sizeDelta = Vector2.one * _currentRow.GetComponent<RectTransform>().rect.width / 2;
}
}
// Don't mind this further it is just for adding the
// AddChild button to the inspector for the example
[CustomEditor(typeof(GridWith2Columns), true)]
private class AddchildsEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
EditorGUILayout.Space();
if (GUILayout.Button("Add Child"))
{
((GridWith2Columns)target).AddChild();
}
}
}
}