ScrollView

Hello. I want to use a scrollview but I cannot find one example how of how to use it programmatically. can anyone show me how to add items to it. I am so frustrated. thanks bye.

To add to a scroll rect or scroll view you add new objects as children of the content object.

If you want a scrolling list, then you need to have a vertical layout group, with your list items as children of that.

Ok thanks for the advice. I tried it on my own but cant get it to work. Unity ui is so hard for me.

Image sv = GameObject.Find(“ScrollView”).GetComponent();

BoxCollider2D boxCollider2D = sv.gameObject.AddComponent();
boxCollider2D.size = new Vector2(
sv.gameObject.GetComponent().sizeDelta.x,
sv.gameObject.GetComponent().sizeDelta.y
);

VerticalLayoutGroup glg = sv.gameObject.AddComponent();

GameObject go1 = new GameObject(“Contacts 22” ); // each invididual contact panel on the list
go1.transform.SetParent(sv.gameObject.transform);

RectTransform trans11 = go1.AddComponent();
trans11.anchoredPosition = new Vector2(0, 0);

Image im = go1.AddComponent();

im.color = Color.red;

Set_Height(im, 40.0f);

This does not work, what am I doing wrong, thanks.

The best thing to do is set it up in the editor first, make sure it looks right, then set it up in code the same way.

1 Like

why isnt there just a sample of this on the internet. I can make it in the editor by adding a scrollview the adding anything I want, thats simple. What about making it programmatically. Unity doesn’t have enough programming documentation, just how to make this in an editior. I have a dynamic list of contacts that changes when my project loads. Thats why I am doing this programmatically.

To expand on some previous feedback, if I were in your situation, I’d create the panel with the vertical layout group. I’d then have 1 prefab setup to be instantiated with the new data. When I wanted to add new data, I’d create a new game object from the prefab, add it to the panel(scrollview) and give whatever specific data it needs at that time.

If you want to try something like that & see how it goes, you could write back here (whether you succeed or fail, doesn’t matter) with your updated code and code tags :slight_smile:

What exactly is it that’s not working? I have been using it in a custom editor window (programmatically). My case gets a little odd because I technically have two scroll views. I am showing some tabular data so I’m showing a header and data below… I wanted to scroll both horizontally but only scroll the data vertically, so I actually sync the “x” value of the header position with the “x” value of the data position. The “y” value of the header position is always zero. So I basically used something like this:

    public class TableDataComponent : EditorComponent
    {
        private Vector2 RecordScrollMarker = new Vector2(0, 0);
        private Vector2 LayoutScrollMarker = new Vector2(0, 0);

        private static Dictionary<Type, Action<IField>> OutputResolvers = new Dictionary<Type, Action<IField>>();

        private static int CellWidth = 150;
        private List<DataRow> _data;

        static TableDataComponent()
        {
            OutputResolvers.Add(typeof(string), GenerateStringField);
            OutputResolvers.Add(typeof(int), GenerateIntField);
            OutputResolvers.Add(typeof(Guid), GenerateGuidField);
            OutputResolvers.Add(typeof(float), GenerateFloatField);
        }

        public TableDataComponent(List<DataRow> data)
        {
            _data = data;
        }

        public override void RenderContent()
        {
            if (_data == null || _data.Count == 0)
                return;

            GUILayout.BeginScrollView(LayoutScrollMarker, GUIStyle.none, GUIStyle.none);

            GUILayout.BeginHorizontal();
            var firstRow = _data.First();

            EditorGUILayout.LabelField("", GUILayout.Width(60), GUILayout.MaxWidth(60));

            foreach (var field in firstRow.Fields)
            {
                EditorGUILayout.LabelField(field.FieldName, GUILayout.Width(CellWidth), GUILayout.MaxWidth(CellWidth));
            }

            GUILayout.EndHorizontal();
            GUILayout.EndScrollView();

            RecordScrollMarker = GUILayout.BeginScrollView(RecordScrollMarker);
            LayoutScrollMarker = new Vector2(RecordScrollMarker.x, 0);

            for (var i = 0; i < _data.Count; i++)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Button("Edit", GUILayout.Width(60), GUILayout.MaxWidth(60));
                var record = _data[i];
                for (var j = 0; j < record.Fields.Count; j++)
                {
                    var currentField = record.Fields[j];

                    var resolver = OutputResolvers[currentField.DataType];
                    resolver(currentField);

                }
                GUILayout.EndHorizontal();
            }
            GUILayout.EndScrollView();
        }

        private static void GenerateStringField(IField field)
        {
            var target = field as Field<string>;
            EditorGUILayout.LabelField(target.Value, GUILayout.Width(CellWidth), GUILayout.MaxWidth(CellWidth));
        }

        private static void GenerateGuidField(IField field)
        {
            var target = field as Field<Guid>;
            EditorGUILayout.LabelField(target.Value.ToString(), GUILayout.Width(CellWidth), GUILayout.MaxWidth(CellWidth));
        }

        private static void GenerateIntField(IField field)
        {
            var target = field as Field<int>;
            EditorGUILayout.LabelField(target.Value.ToString(), GUILayout.Width(CellWidth), GUILayout.MaxWidth(CellWidth));
        }

        private static void GenerateFloatField(IField field)
        {
            var target = field as Field<float>;
            EditorGUILayout.LabelField(target.Value.ToString(), GUILayout.Width(CellWidth), GUILayout.MaxWidth(CellWidth));
        }

    }

There’s a lot of code there you don’t need and it’s a little wonky as this was all written for testing purposes and you wouldn’t have all of the types, but it gives you an idea (example) of scroll views working.

Thanks Dustin-Horne but that code is still very differnent from what I am doing.

Thanks methos5k that sounds like what I am doing below. can you please look at my code and tell me if I am doing anything wrong, but Image that I add to a gameObject is not showing up I don’t know why. How can unity expect people to use their UI without any Documentation on how to use it programatically.

Image sv = GameObject.Find("ScrollView").GetComponent<Image>();


BoxCollider2D boxCollider2D = sv.gameObject.AddComponent<BoxCollider2D>();
boxCollider2D.size = new Vector2(
sv.gameObject.GetComponent<RectTransform>().sizeDelta.x,
sv.gameObject.GetComponent<RectTransform>().sizeDelta.y
);

VerticalLayoutGroup glg = sv.gameObject.AddComponent<VerticalLayoutGroup>();

GameObject go1 = new GameObject("Contacts 22" ); // each invididual contact panel on the list
go1.transform.SetParent(sv.gameObject.transform);

RectTransform trans11 = go1.AddComponent<RectTransform>();
trans11.anchoredPosition = new Vector2(0, 0);

Image im = go1.AddComponent<Image>();

im.color = Color.red;

Set_Height(im, 40.0f);

Of course you can do it all in code. However, you could skip the part for creating the scroll view in code, as well as the game object with image for each contact panel, I guess they are.

The scroll view panel could be created in the scene once and its contact panels can be added from a prefab, as I tried to say before.

Anyways, back to the question, I am not sure why your code is not working. Does it have any errors or anything?

Plus, it’s hard to read that… I mean, it looks like you’re adding a layout group, but do you just do that once? I mean, I’m not sure how you add your “dynamic contacts”.

I’m certain if you google you can find an example of a dynamically populated list. Unity also has some of the best documentation of any game engine I’ve used, including the UI. There’s scripting API entries for every component we’ve mentioned.

No one is questioning why you’re doing this programmatically, but there’s no reason to do literally everything in code. You can set up almost all of it in the editor (because it’s way easier), and then only code the dynamic portions. If you have a list that gets filled dynamically, create the entire list UI in the editor, make a “list item” prefab in the editor (make sure it looks right in the list in the editor), and then spawn the list item prefabs into the list with code when the game loads.

Hey Thanks. I got it partially working. I kinda did what you said jeffreyschoch. I couldnt add content to the scrollview at all, so I figured out that I could add stuff to the content element of the scrollview in the editor. So I got a handle on the panel from inside my code and added some images to it. It looks ok for now. The problem, is that if i add alot of images to the panel in the scrollview, the content of the panel will not overflow and the scrollbar doesnt work when I do this. I want to have a large list of items and be able to scroll down them. I tried a content size fitter on my panel bu that didnt work. I have one more problem when I add a list of images to the panel in the scrollview, the images 0 to 20 for example don’t start at the exact top of the panel, they start somwhere in the middle. I have a pic to illustrate this. See where it says contact to that starts at the top of the scrollview but above it is contact 0 , contact 1. So I am very close please help thanks.

Also, the above is what happens when I add 5 items to the panel that’s in the scroll view. the following happens when I add 20, how can I make it so that the items stay the same size and the panel and scroll view change size intead so I can use the scrollbar? thanks

Content size fitter on the content portion is the way to go for an expanding scroll view.
As for the elements, you can set their pivot/anchor to the top left if that’s where you want them to start…I think that’s what I usually do.
Try playing with some options on the vertical layout group so the size doesn’t change like that, I think.

Image sv = GameObject.Find("Image").GetComponent<Image>();

ContentSizeFitter csf0 = sv.gameObject.AddComponent<ContentSizeFitter>();

Here is my attempt at setting the minHeight for the children of that Image. Don’t know how else to set the height for the children of the Image.

        //Assign all the children of the content panel to an array.
        LayoutElement[] myLayoutElements = sv.gameObject.GetComponentsInChildren<LayoutElement>();

        //For each child in the array change its LayoutElement's minimum height size to 64.
        foreach (LayoutElement element in myLayoutElements)
        {
            element.minHeight = 64f;
        }

I cant figure out how to set the pivot of the Image. The Image that I use to add all my children to has its rect Tranform set to top left. This doesnt stop the blue children from adding them selves not aligned.
3097309--233791--Untitled2.png

Any tips thanks?

The VerticalLayoutGroup should have a property for child alignment, and should control the positioning and sizing of child elements entirely. It also has an option for whether the children should stretch to fit, although if you get your ContentSizeFitter working properly, they won’t have to change size to fit because there will always be enough room.

Here’s a guide for a similar implementation that might help you along: Creating Dynamic Scrollable Lists with New Unity Canvas UI - folio3

When you click on that little positioning icon/image there in the RectTransform… read the information there. There are some key combination/shortcuts you can use for fast presets. Also, the pivot top left would be: x = 0, y = 1

Plus, @LiterallyJeff responded as I was writing, so try that stuff, too.

1 Like

I am reading Creating Dynamic Scrollable Lists with New Unity Canvas UI - folio3
They use a listItem as a prefab, what kind of ui is a ListItem, I cant find it in my list of items to use.thanks

I skimmed that to see what you were talking about… and came to the conclusion that you either didn’t read it, or you read & forgot… (and should read that section, again). :slight_smile:
It’s there, they explain it…

Their ‘list item’ is comprised of a few pieces, and then made into a prefab for re-use in the code :wink:

Sorry about that. Misunderstood what it was you were doing. :slight_smile:

Amazing guys. I finally figured it out, I see what you mean by doing most of the work in the editor. I have two pics of the results that I got, for a list of contacts that I dynamically populate. The only problem left is that the contact list starts at the half way point of the list. Say there is 100 contacts, the list will start at 50. I can scroll up and down it. How do I make that list create and start at 0? Here is pics