Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

ScrollRect : how to dynamically increase the content size ?

Discussion in 'UGUI & TextMesh Pro' started by bali33, Aug 26, 2014.

  1. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    Hi,

    I'm was wondering how to update the content size of a ScrollRect component ?

    Let's say I have a Panel which is assigned as the RectTransform Content of a ScrollRect component - by default the scrolling area is based on the Content RectTransform size - But the size it's not related to the children GameObject of the Panel. So if I add Button programmatically into my Panel, its RectTransform does not change, so tI will never see those Buttons.

    To make it simple, I try to simulate a list which is dynamically populated - Is it possible ?

    Thank you
     
    J.Mad likes this.
  2. Lidanh

    Lidanh

    Joined:
    Mar 27, 2013
    Posts:
    29
  3. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    Hi,

    I'm going to take a look right now and see if it answers my problem :)

    Thank you
     
  4. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    @Lidanh

    Your Grid component, the one with the GridLayout, has a no editable height, which let me think its size is dynamic. In my test project I added a VerticalLayout into my container, the one that will contain my buttons, but the height size is editable and when the buttons are added its size does not change, the buttons are not visible (but visible in the hierarchy when they are created).

    Do I have to do something special in order to have my container height dynamic ?

    Thank you
     
  5. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    Ok, I didn't understand that the Content Size Filter was mandatory.

    Sorry and thanks again.
     
    TheDarkVoice and Sandrok like this.
  6. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    I have another question, how to not have my buttons deformed by the VerticalLayout ? My Button pref is 100x25 but the prefab instances are 100x10 -> 10 px is also the height of the container when it is empty, this value is automatic and not editable.
     
  7. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,840
    Put a LayoutElement component on the button and specify a Min Width and Min Height there.
     
    EDevJogos and Mycroft like this.
  8. bali33

    bali33

    Joined:
    Aug 14, 2011
    Posts:
    188
    Ok, I'll try this solution.

    Thank you.
     
  9. Foxxis

    Foxxis

    Joined:
    Jun 27, 2006
    Posts:
    1,108
    I cannot get this to work. Scenario:

    Scrollrect with image and mask
    - gridlayout with default width/height
    - - layoutelement
    - - layoutelement
    - - .....

    I would have expected the Scrollrect to consider the gridlayout total size and the gridlayout to dynamically resize as layout elements are added to the hierarchy. As it is, the only variables that seem to have effect on the scolling is the gridlayout width and height. The scrollrect does not care whether there is content below or not.
    Does this mean that we have to calculate an appropriate gridlayout width/height at runtime in order for scrolling to work, or am I missing something?
    Surely the scollrect and gridlayout in combo should be intelligent enough to set correct scrolling bounds...?

    Thanks in advance!
     
  10. Foxxis

    Foxxis

    Joined:
    Jun 27, 2006
    Posts:
    1,108
    Never mind. It was easily solved by a ContentSizeFitter component. My apologies for the ignorance.

    (The content size fitter on the same object as the grid layout will enable automatic resizing of the content rect.)
     
  11. Foxxis

    Foxxis

    Joined:
    Jun 27, 2006
    Posts:
    1,108
    Still have one problem:
    When repopulating a scrollrect, the scrollview is incorrect until I drag the scrollbar at which point the view will "snap" to the correct view. Is there a function I can call to force a recalculation of the scrollrect position? I cannot seem to find any... :-/
     
  12. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    For me ContentSizeFitter doesn't work. I have to calculate the Content size/pos by hand. Something like:

    Code (csharp):
    1. var itemWidth = 125f;
    2. var totalItems = content.childCount;
    3. var newContentWidth = itemWidth * totalItems + spacing.x * totalItems;
    4. var t = content.GetComponent<RectTransform>();
    5. t.sizeDelta = new Vector2(newContentWidth, t.sizeDelta.y);
    6. t.anchoredPosition = new Vector3(newContentWidth * 0.5f, t.anchoredPosition.y);
    Would be better a builtin option to make that for me.
     
  13. Murkas

    Murkas

    Joined:
    Jul 24, 2013
    Posts:
    7
    Should be the solution to your problem.
     
  14. Foxxis

    Foxxis

    Joined:
    Jun 27, 2006
    Posts:
    1,108
    Can only confirm that ContentSizeFitter does not work for me either. The content does have LayoutElement components with the correct mindimensions, but the positioning of the gridlayoutgroup that is being scrolled is being incorrectly positioned. When I remove the ContentSizeFitter and manually scale the gridlayout, all problems associated with incorrect positioning and weirdly acting scrollbars goes away.
    Are we missing something? The documentation for these components and especially their implications in dynamic situations is quite scarce.
    Thanks in advance!
     
  15. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,840
    The thread was originally about making the context rect fit the content. That can be done with a ContentSizeFitter. If that doesn't work for you, then I don't have enough information to be able to say why.

    However, you're also making comments about the positioning (not size) being wrong. That's a different issue. Beta 19 will have the following fix: "Fixed issue in ScrollRect when content is smaller than view, where scrolling position would jump around."

    If you think that might fix your issues, then wait for beta 19. If not, then file a bug report with attached repro project and description of repro steps.
     
  16. hexagonius

    hexagonius

    Joined:
    Mar 26, 2013
    Posts:
    98
    I am having trouble with getting this to work with several ScrollViews in a vertical layout group. I want the group to inherit the hight of the whole content. So I am using the content size fitter along with the vertical layout group. For the inheritance of the sizes of the scrollview contents, I need to provide layout groups all the way through the hierarchy, right? I can't for the life of me keep the width of either the scrollRect, OR the ViewPort (if it exists) to stay as wide as the screens width while its child adjusts to its respective content. I cannot use a second Content Size Fitter either, because the whole hierarchy uses layout groups.... HOW do you do that?
     
  17. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,840
    There are lots of answered posts already with questions about ContentSizeFitter + ScrollViews. I would suggest searching around a bit and look at those. If none of that helps, I'd recommend starting a new thread and describe your setip in much more detail, possibly with a screencast. From your description I can't tell what you're referring to when you talk about "the whole content", whether you have layout groups both inside the scrollviews and outside, etc.
     
  18. Firedan1176

    Firedan1176

    Joined:
    Dec 7, 2013
    Posts:
    48
    Hey, guys! I've come up with a simple script that will do EXACTLY what you want. It simply does math to expand the size of the RectTransform. Here's the steps:

    1. Create a Panel to hold your dynamic buttons
    2. Add a GridLayoutGroup component to it (it must be a GridLayoutGroup)
    3. Set the panel's anchor and especially the pivot to the top left corner.
    4. Add the following script:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5.  
    6. public class DynamicScrollFitter : MonoBehaviour {
    7.  
    8.     public bool expandX, expandY = true;
    9.  
    10.     RectTransform myTransform;
    11.     GridLayoutGroup layoutGroup;
    12.  
    13.     Vector2 cellSize;
    14.     RectOffset padding;
    15.  
    16.     Vector2 newScale;
    17.  
    18.     // Use this for initialization
    19.     void Start () {
    20.  
    21.         myTransform = GetComponent<RectTransform>();
    22.         layoutGroup = GetComponent<GridLayoutGroup>();
    23.         cellSize = layoutGroup.cellSize;
    24.         padding = layoutGroup.padding;
    25.  
    26.     }
    27.  
    28.     void OnGUI() {
    29.         newScale = myTransform.sizeDelta;
    30.  
    31.         if (expandX) newScale.x = padding.left + padding.right + ((cellSize.x + layoutGroup.spacing.x) * transform.childCount);
    32.         if (expandY) newScale.y = padding.top + padding.bottom + ((cellSize.y + layoutGroup.spacing.y) * transform.childCount);
    33.  
    34.         myTransform.sizeDelta = newScale;
    35.     }
    36. }
    37.  
    EDIT
    Now of course you don't have to use both X and Y. In my case, I don't need X at all, so you should simply take out the code that involves the expandX boolean.

    Let me know if you guys get any problems with this.
     
  19. TimGS

    TimGS

    Joined:
    Apr 24, 2014
    Posts:
    63
    Congratulations. You've just reinvented a wheel.

    Search for ContentSizeFitter in docs and you'll be surprised. ;)
     
  20. KOKOStern

    KOKOStern

    Joined:
    Dec 22, 2013
    Posts:
    13
    @Firedan1176 - I was looking for a solution and I was sad to see it really comes down to what you did in that script, which seems super obvious and should be a tick-box in the core Unity components, but for some reason isn't. Well done.

    @TimGS - Totally not correct. Using a ContentSizeFitter on a GridLayout that serves as the content for a ScrollRect will tell you that you shouldn't use it because the size is controlled by another Layout component. Sadly the current Layout components simply don't have these options.
     
  21. Supergeek

    Supergeek

    Joined:
    Aug 13, 2010
    Posts:
    94
    I believe if you create an empty GO and attach your content underneath it, then put the ContentSizeFitter on the empty GO, it will eliminate the warning and still work.
     
  22. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,840
    I have trouble following the exact scenarios that are causing trouble here, but one thing to be aware of is that some issues can be solved by using the new ScrollView structure you get if you choose GameObject > UI > Scroll View. Specifically, a sctructure where there is an explicit Viewport GameObject that's placed in between the ScrollRect and the Content.

    In cases where the ScrollRect and Viewport are the same GameObject, there can sometimes be issues.
     
  23. KOKOStern

    KOKOStern

    Joined:
    Dec 22, 2013
    Posts:
    13
    After further tests I found out that the code previously mentioned by Firedan1176 isn't actually needed.

    Using a ContentSizeFitter gives out a warning but does actually work.

    The issue is that the ContentSizeFitter believes ScrollRect is a LayoutGroup and thus doesn't like being a direct child of it.

    Having an intermediary Viewport Gameobject between the ScrollRect and the Content (like runevision suggests) will 'solve' this issue.

    My main question is why would I need that Viewport?

    I don't exactly see an issue with having a Mask on the ScrollRect GameObject itself, and the content directly nested below. This also makes perfect sense - the ScrollRect has content that it scrolls and you may also want to have a mask for said content (don't have to use one). This makes sense and should be the way it works. All this confusion stems because it supposedly doesn't (again - it does but gives a warning).

    The current way the ScrollRect is 'suppose' to work (as suggested by runevision) basically means each 'part' of the ScrollRect can be totally separate. You can put the Content, the Viewport and the Scrollbar on totally different GameObjects and it'll be ok. This gives out greater versatility (I guess?), but man is it unintuitive.

    Personally I'm not entirely sure of the use for the Viewport. Why can't the ScrollRect object itself serve as a Viewport? I don't understand the use case for that separation, but I'm assuming there's a good one.

    Note: just to be clear - it totally work. My ScrollRect doesn't reference any Viewport and just has the content nested directly below it, but it's not 'suppose' to work that way.
     
    DoomGoober likes this.
  24. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,840
    Basically this is to support scrollbars that can appear or disappear based on whether they are needed (typical scrollbar functionality). This in turn can modify the size of the viewport, because it needs to compensate for whether the scrollbars take up space or not. This means the viewport is sometimes smaller than the total scroll rect (which includes the scrollbars). In order for the ScrollRect to automatically adjust the size of the viewport, it needs to act like a layout group.

    Now, not everyone use scrollbars, let alone scrollbars that can auto-hide and modify the size of the viewport. But we don't have a way of making a component only sometimes be a layout group. Either it's a layout group or it's not. So this introduced the need to have a separate viewport so that the layout system doesn't think the ScrollRect is trying to control the size of the Content itself. It was hard to avoid this without introducing major changes to how the layout system works.
     
  25. KOKOStern

    KOKOStern

    Joined:
    Dec 22, 2013
    Posts:
    13
    I see. Interesting case where trying to solve a specific problem makes the general case much more convoluted.

    At the very least, the warning on the ContentSizeFitter in this case should be a little more clear and mention that despite the warning, it still works.
     
    MV10 and hexagonius like this.
  26. khokhani1510

    khokhani1510

    Joined:
    Jun 26, 2013
    Posts:
    36

    Yeh, correct..its so simple, just add ContentSizeFilter to scroll view component, it will automatically resize and rect view will expand!
     
  27. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    427
    This will handle content with multiple columns

    (((cellSize.y + layoutGroup.spacing.y) * transform.childCount) / layoutGroup.constraintCount

    Never did get ContentSizeFilter to work !

     
  28. UNITY3D_TEAM

    UNITY3D_TEAM

    Joined:
    Apr 23, 2012
    Posts:
    720
    yes its working with content sizefilter
     
  29. fafase

    fafase

    Joined:
    Jul 3, 2012
    Posts:
    156
    After flying over that thread, I was looking for a solution related to expansion of the box with text.
    Most solutions here seem to deal with layout and grid and buttons and so on.

    So maybe this is already solved above but I'll just put it again coz it got me cringing deeply at Unity UI though it works.

    You add a scroll view object. This will include by default:
    • Scrollview
    • Viewport
    • Content

    Now add a Text component to the Content object, NOT a text child, a component to it. Also add a ContentSizeFitter and set the vertical fit to prefered size. This is because I will deal with vertical expansion.

    Make sure the Viewport occupies the space that should serve as mask. For first practice, place the ScrollView object in the middle and set the anchors of Viewport to 0,1 so it takes the whole parent.

    Now you can run and start typing in the text component. As you reach the bottom, it will expand automatically, the scroll bar will appear. You are now happy and strongly considering sending a donation to fafase help center for kids who can code good.
     
    Last edited: Nov 13, 2018
  30. karsnen

    karsnen

    Joined:
    Feb 9, 2014
    Posts:
    65
  31. Mohammed-Rehman

    Mohammed-Rehman

    Joined:
    Sep 21, 2015
    Posts:
    1
    Thank you it work perfectly just switch to preferred size in Vertical Fit Content size Fitter
     
  32. DoomGoober

    DoomGoober

    Joined:
    Dec 12, 2013
    Posts:
    7
    Sorry to necro this thread but here's the exact GameObjects/components I have that solve this problem (basically all the info on this thread turned into an example). In this case, I have a horizontal layout group that dynamically grows to the right, children fill the height, and I want to scroll left/right. Settings on components only show difference from defaults:
    • ScrollRect (ScrollRect(Horizontal:True))
      • Viewport (Image, Mask, ContentSizeFitter(Unconstrained,Unconstrained)) Ignore warning on ContentSizeFitter!
        • Contents (HorizontalLayoutGroup(ControlChildSize:Width, ChildForceExpand:Height), ContentSizeFitter(HorizontalFit: PreferredSize,VerticalFit:Unconstrained)))
    Thanks for all the help! I hope this helps someone else.
     
    Last edited: Feb 29, 2020
    snowinrain likes this.
  33. snowinrain

    snowinrain

    Joined:
    Jan 17, 2016
    Posts:
    7
    This works for me. However, I don't need ContentSizeFitter in Viewport
     
  34. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    1,975
    really complicated and can't apply. too much, don't know how to even start.

    I want dynamically enlarge, shrimp some scrollview element's height, and let other element's y position aligned to it.

    Contents (HorizontalLayoutGroup(ControlChildSize:Width, ChildForceExpand:Height)

    sudden check one of these make existing element's height, position, its child elements become total mess, so can't check any of them.
     
    Last edited: Aug 21, 2020
unityunity