Order of elements in Layout Groups

When using a Horizontal, Vertical, or Grid Layout Group, is there any way to control the order of the elements?

I imagine this is a common thing: You add a handful of elements to a panel with a Layout Group, then want to make sure they’re sorted by their display name (or id, or value, or whatever other property interests you).

My understanding is that you order the children of the layout in the order you want them to appear.

Interesting.

I’m adding elements to my UI dynamically at runtime through scripts. Would this mean they’re sorted based on the order in which they’re added? To change the order, would I need to remove them all and then re-add them to the parent panel in the order I want to see?

1 Like

Yes.

No.
http://docs.unity3d.com/460/Documentation/ScriptReference/RectTransform.html
SetAsFirstSibling - Move the transform to the start of the local transfrom list.
SetAsLastSibling - Move the transform to the end of the local transfrom list.
SetSiblingIndex - Sets the sibling index.

15 Likes

Perfect, thanks!

Also there is a bug with applying ordering changes for layout in runtime How to change hierarchy order in layout groups through code - Unity Engine - Unity Discussions so you’ll have to workaround it for now.

exactly wat i was searching for from days!!!..Thansks ur a life saver!! :slight_smile: :stuck_out_tongue:

when you use SetSiblingIndex does the index have to be a valid number (e.g. 0-9 if there are 10 elements) or can it be an arbitrary integer outside the 0-9 range? … used for say weighted priority sorting.

Interesting… but Probably not?!? :[

when i have kissUI autosort, it does the same thing… well, except for children in a Layout. It sets the immediate children at the same Depth. Does unityUI do that too, i wonder.

I have a my list sorted but I have no idea how can I apply that sorting to their siblings.

///Instantiate your stuff into panel and then randomise
GameObject _card = Instantiate(card_prefab, transform.position, transform.rotation) as GameObject;
_card.transform.position = tempPositionAndScale;
_card.transform.SetParent(cardPanel.transform, false);

//or order the child elements in panel..
public void OrderPanelAlpabetically()
{
GameObject[ ] count = GameObject.FindGameObjectsWithTag("CardsPanel");
GameObject[ ] countOrdered = count.OrderBy(go => go.name).ToArray();
for (int i = 0; i < countOrdered.Length; i++)
{
countOrdered*.transform.SetSiblingIndex(i);*
*}*
*}```*

I’m having the Problem, that I need the vertical layout group inverted. So first child should be at the bottom, second on top of that. But in the Hierarchie the should remain the same. Anybody got a solution for that?

2 Likes

That’s what I needed too. This doesn’t seem to be done right out of the box though it really could have been a basic functionality.

To make it work bare bones you have to reverse the loop inside the Unity UI’s class HorizontalOrVerticalLayoutGroup in the SetChildrenAlongAxis method.

Change the following in two places:

for (int i = 0; i < rectChildren.Count; i++)

to a reverse:

 for (int i = rectChildren.Count - 1; i >= 0; i--)

This should effectively reverse distribution along axes and depth sorting too.

You will probably want to be able to toggle the reversion, so make something like this:

for (int i = m_Reverse ? rectChildren.Count - 1 : 0; m_Reverse ? i >= 0 : i < rectChildren.Count; i += m_Reverse ? -1 : 1)

Be sure to expose ‘m_Reverse’ in the inspector.

I might just steal that and put it in, sounds handy. (no promises though)

3 Likes

should land for 2020. Before its asked sorry wont be backported as it doesnt meet the requirements for 19.3 as we try to stabilize.

3 Likes

Here is the solution I came up with:

namespace UnityEngine.UI
{
    [AddComponentMenu("Layout/Reverse Vertical Layout Group")]

    public class ReverseVerticalLayoutGroup : VerticalLayoutGroup
    {
        protected ReverseVerticalLayoutGroup() { }

        /// <summary>
        /// This allows for UI elements to remain in the hierarchy according to draw order
        /// while allowing them to display in reversed vertical order.
        /// </summary>
        public override void SetLayoutVertical()
        {
            RectTransform[] reversedRectChildren = new RectTransform[rectChildren.Count];
            int rectChildrenCount = rectChildren.Count;
            int lastIndex = rectChildrenCount - 1;
            for (int i = lastIndex; i >= 0; i--)
                reversedRectChildren[lastIndex - i] = rectChildren[i];
            for (int i = 0; i < rectChildrenCount; i++)
                rectChildren[i] = reversedRectChildren[i];

            base.SetLayoutVertical();
        }
    }
}
1 Like

Thank you for helping me!

Sort your list however you want, then Transform.SetSiblingIndex(i)