1

I thought this would be like pretty simple task to do, but now I have tried for hours and cant figure out how to get around this.

I have a list of friends which should be displayed in a scrollable list. Each friend have a profile image and a name associated to him, so each item in the list should display the image and the name.

The problem is that I cant figure out how to make a flexible container that contains both the image and the name label. I want to be able to change the width and height dynamically so that the image and the text will scale and move accordingly.

I am using Unity 5 and Unity UI.

I want to achieve the following for the container:

  • The width and height of the container should be flexible
  • The image is a child of the container and should be left aligned, the height should fill the container height and should keep its aspect ratio.
  • The name label is a child of the contianer and should be left aligned to the image with 15 px left padding. The width of the text should fill the rest of the space in the container.

Hope this is illustrated well in the following attached image:

enter image description here

I asked the same question here on Unity Answers, but no answers so far. Is it really possible that such a simple task is not doable in Unity UI without using code?

Thanks a lot for your time!

jake
  • 73
  • 1
  • 2
  • 6
  • fortunately it is VERY EASY to do WITHOUT code. you're looking for the **HorizontalLayoutGroup** - phew! – Fattie Sep 18 '20 at 17:45

2 Answers2

0

Looks like can be achieved with layout components.

The image is a child of the container and should be left aligned, the height should fill the container height and should keep its aspect ratio.

For this try to add Aspect Ratio Fitter Component with Aspect mode - Width Controls Height

enter image description here

The name label is a child of the container and should be left aligned to the image with 15 px left padding. The width of the text should fill the rest of the space in the container.

For this you can simply anchor and stretch your label to the container size and use BestFit option on the Text component

enter image description here

Greg Lukosek
  • 1,774
  • 20
  • 40
  • I have tried something similar. By "layout components" do you mean Layout Group? I tried doing what you suggested, and almost works. Only problem is that when i change the container height the image does not fill the height because of the aspect fitter. I want the image to always fill the height of the container, keep its aspect ratio and push the labels position to the right as the image gets bigger. Does that makes sense? Thanks. – jake Jun 04 '15 at 07:52
  • Just set Height controls width in Aspect Ratio Fitter AND make sure you use height stretch with top and bottom values in Rect transform as 0 – Greg Lukosek Jun 04 '15 at 10:30
  • I tried that, but cant see how you would anchor the label to the right side of the image this way. It works fine when the container width is changed, but if the height of the container is changed, the label wont stick to the image. – jake Jun 04 '15 at 11:50
0

We never found a way to do this without code. I am very unsatisfied that such a simple task cannot be done in the current UI system. We did create the following layout script that does the trick (tanks to Angry Ant for helping us out). The script is attached to the text label:

using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent (typeof (RectTransform))]
public class IndentByHeightFitter : UIBehaviour,        UnityEngine.UI.ILayoutSelfController
{
public enum Edge
{
    Left,
    Right
}

[SerializeField] Edge m_Edge = Edge.Left;
[SerializeField] float border;

public virtual void SetLayoutHorizontal ()
{
    UpdateRect ();
}


public virtual void SetLayoutVertical() {}

#if UNITY_EDITOR
protected override void OnValidate ()
{
    UpdateRect ();
}
#endif


protected override void OnRectTransformDimensionsChange ()
{
    UpdateRect ();
}


Vector2 GetParentSize ()
{
    RectTransform parent = transform.parent as RectTransform;

    return parent == null ? Vector2.zero : parent.rect.size;
}


RectTransform.Edge IndentEdgeToRectEdge (Edge edge)
{
    return edge == Edge.Left ? RectTransform.Edge.Left : RectTransform.Edge.Right;
}


void UpdateRect ()
{
    RectTransform rect = (RectTransform)transform;
    Vector2 parentSize = GetParentSize ();

    rect.SetInsetAndSizeFromParentEdge (IndentEdgeToRectEdge (m_Edge), parentSize.y + border, parentSize.x - parentSize.y);
}
}
jake
  • 73
  • 1
  • 2
  • 6