How to keep frame size within a scrolling frame

Hi there

I have been trying to create some UI for my game and it was going pretty well… until I fell into this problem.
I have a scrolling frame with a UIGridLayout

image

I have made it all to look fine at the current resolution,

but as soon as I resize the screen, the frame does this:

image

I can’t use scale due to the fact that the scrolling frame’s canvas size will be changing and it looks squished. Is there any way to keep it the same size but smaller (if that makes any sense)?

2 Likes

Try using Scale but with the UIAspectRatio object in the Frame
If that one doesn’t work… you might also want to listen to GetPropertyChangedSignal’Size’ and script it to set the Frames’ sizes to a specific size

5 Likes

Have you looked into the use of constraints more?
I think what you’re looking for is “UISizeConstraint”.

If you put this inside a frame, and give it a min and a max, it should not size any larger than that max value, or go below the min value.

You’re using Offset, right?

There is not a built-in solution to this at this stage, so we’ll need to do some scripting to fix it. Firstly, though, you should do what PlantChampion said and use a UIAspectRatioConstraint (to make sure your frame is always square) and then listen for a signal. I will go more in-depth on this signal part.

You’ll need to essentially make your own Scale system. The Scale system of children of a ScrollingFrame effectively use ScrollingFrame.AbsoluteCanvasSize to calculate their size, unlike every other object wich uses Object.AbsoluteSize. So, all you really need to do is calculate with AbsoluteSize instead of AbsoluteCanvasSize. Calculating scale itself is pretty easy since you just do PARENT_SIZE * SCALE_SIZE. You’ll need to actually run this code, so here’s where the signal comes in. You’ll just need to listen to the signal for when the AbsoluteSize of the ScrollingFrame gets changed. Here’s some code demonstrating how this can be done:

-- This lets you configure what you want the size to be normally without having to change to script
local TargetScaleSize = Frame.Size

local function UpdateScale()
    local ParentSize = ScrollingFrame.AbsoluteSize

    -- Converting the scale size to pixels and then adding on any offsets
    local X = (ParentSize.X * TargetScaleSize.X.Scale) + TargetScaleSize.X.Offset
    local Y = (ParentSize.Y * TargetScaleSize.Y.Scale) + TargetScaleSize.Y.Offset

    Frame.Size = UDim2.new(0, X, 0, Y)
end

ScrollingFrame:GetPropertyChangedSignal("AbsoluteSize"):Connect(UpdateScale)
UpdateScale()
7 Likes

Would it be fine to do this

local TargetScaleSize = UDim2.new(0,100,0,100)

Rather than this

local TargetScaleSize = Frame.Size

Because what I am doing is creating a different number of frames every time this GUI enters the PlayerGui and then the sizes are controlled by a UIGridConstraint.

Problem is though, because the CellSize is {0,100,0,100}, this part

local X = (ParentSize.X * TargetScaleSize.X.Scale) + TargetScaleSize.X.Offset
local Y = (ParentSize.Y * TargetScaleSize.Y.Scale) + TargetScaleSize.Y.Offset

will always equal 0,100,0,100

2 Likes

With a big logical headache, I have managed to get it to work with my setup. Thanks @PlantChampion @Partcline and @EmeraldSlash for your great responses :smile:

3 Likes

This is where you should be setting the TargetScaleSize in Scale. If your entire container frame scales with screen size, having its children (in this case, the grid items) scale would be a good idea too, and that’s where this solution really shines in my experience. You’ll just need to manually find the Scale values you want. Anyway, I’m aware you have fixed it so good job :wink:

2 Likes

That makes sense probably more so than my own edit of your code. I’ll have to tweak around in a few days. Merry Christmas!! to everyone celebrating!

Yeah, you too! Already got my presents now because New Zealand is so far ahead in time lol

Of course yeah. It’s 19:00 Christmas Eve in England rn. :smile:

1 Like

I’d like to comment on this and say that this no longer requires any scripting. Here is my solution:

  1. Add a UIGridLayout to the ScrollingFrame.
  2. Add a UIAspectRatioConstraint to each member of the ScrollingFrame (which would be 1 since it’s a square).
  3. For some reason, using this application mixture of UIGridLayout and UIAspectRatioConstraint makes each member move with an axis in the Y dimension. Make one Scale CellSize of the UIGridLayout to be the size of the square. Make the other Scale dimension to be small enough so that the member doesn’t move position.
3 Likes