如何在Unity3d中仅将两个对象设置为水平组布局?

时间:2019-02-12 06:33:28

标签: c# unity3d layout

我要实现的目标类似于GridLayout技术。在Grid Layout中有一个Constraint-Fixed Coloumn Count选项,我将该值设置为2.Grid布局的问题是,当我们将像元大小设置为一个特定的值之后,单元格的大小将不会扩展到所有其他屏幕大小,因此尝试仅用两个列手动设置Horizo​​ntalGroup Layout,问题就在于当我需要实例化许多项目时,它应该以顺序1排列第一行2个项目,第二行3,4个项目,依此类推。 我在Gridview上尝试过的一个在Link

中给出

1 个答案:

答案 0 :(得分:2)

我使用HorizontalLayoutGroupVerticalLayoutGroup和简单的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宽度

    • childControlHeight = true;
    • childControlWidth = true;
    • childForceExpandHeight = true;
    • childForceExpandWidth = true;

    和一个ContentSizeFitter(仅用于扩展底部的背景,或者用于滚动时使用)

  • 它将附加行。一行需要HorizontalLayoutGroup

    • childControlHeight = false; (高度将由StayQuadratic控制)
    • childControlWidth = true;
    • childForceExpandHeight = true;
    • childForceExpandWidth = true;

我制作了以下脚本进行设置。对于此示例,我只生成所有对象和项目,但是您当然也可以使用具有相同设置的预制件。

[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();
            }
        }
    }
}

enter image description here