Scaling for UIListLayout's content

Here is a settings UI that I am working on, and the list content is not scaling correctly because I used I used offset for the frames inside the UI list.

Full screen:

Windowed:
image

And If I want to switch to using scale while maintaining a correct size for the frames, is this the only solution?

First: Set the canvas size same as the scrolling frame’s size.
image

Secondly: decide the Y scale of each frame. In this case I will have each frame have the height scale of 0.1. which means 10 of these frames will fit in one “page”.
image

Thirdly, when a new frame get added, increase the canvas size by the new frame’s Y scale.
So in this case, the canvas size will be 0.725 + 0.1 = 0.825.
image

Lastly, set each frame’s Y scale equally by (1/number of frames), originally there are 10 frames, each of them are 0.1, after a new frame is being added, the scale will be 1/11, which is 0.90909

Result:
Image from Gyazo
From the GIF above, you can see all options are being seen in no matter what screen sizes.

However, with only using offset, option 8 can not be seen on smaller screens.
Image from Gyazo

Is this the only solution if I want the options to be scaled correctly in all screen sizes? My concerns are what if the UIs inside the list are different in size? And is that much calculations, and setting the sizes really necessary? Is there better alternatives?

3 Likes

What you can do is add a “UIAspectRatioConstaint” into each frame and set the DominantAxis to “Width” and tinker with the AspectRatio property till you get the correct size you need.

1 Like

I have a repro here, can you have a look and configure the UIAspectRatioConstaint well? I don’t know how to configure them well.
ScrollingFrame_Repro.rbxl (42.7 KB)

My goal is to have the options scaled to the screen, while the scrolling canvas size fits the number of frames in the container.

In my experience, using scaling in scrolling frames is generally buggy. What I’ll typically do is keep the amount of scaling on the X-axis but use offset on the Y.

Since scrolling frames typically doesn’t use the X-axis for the CanvasSize property you can set that to 0.

To work around this, everytime I update the items in the scrolling frame, I’ll set the initial size of that frame and set a local variable as a template for each clone.

This is probably better ellaborated in the form of code rather than explained via text, so I’ll give a sort of rough idea of what that’d look like.

Some extra details I should mention is that generally you don’t want to use the “ContentSize” property in ScrollingFrames since that’ll put it into a constant loop of updating the canvas size, especially if you update in a Property Change event. Generally, it’s best you calculate CanvasSize yourself.

It’s somewhat unfortunate that Roblox’s UI engine is so counterintuitive, but you just learn over time to work around the issues.

local yAxisSize -- this will be used for a basepoint for calculating the size
for i, data in ipairs(...) do
	local template = template:Clone()
	template.ListOrder = i
	if yAxisSize then
		template.Scale = yAxisSize
	end
	... -- update the name and properties of the template here
	template.Parent = scrollingFrame -- absolutesize is calculated in roblox's engine, you can now set it

	if not yAxisSize then
		yAxisSize = template.AbsoluteSize -- i opted to just set offset as the absoluteSize to save time but it's up to you whether or not you want to use both scaling and offset
		template.Size = UDim.fromOffset(yAxisSize.X, yAxisSize.Y)
	end

	if yAxisSize then -- this conditional basically makes sure that all this logic was applied before updating the canvasSize
		scrollingFrame.CanvasSize = UDim.fromOffset(0, (yAxisSize.Y * i) + (i * UIListLayout.Padding.Offset)) -- i set the x size to zero since I don't really see a use for sideways scrolling but your milage may differ
		-- i should also mention that i used i - 1 because you shouldn't account for extra padding on the scrollingframe
		-- also, don't use scale for padding as well since many inconsistencies can happen.  a general rule of thumb is that offset is the only thing you should use in scrollingframes (or with UIConstraints in general)
	end

end

Anyway, that’s just my two cents, UI tends to be a pain in the ass and hopefully I can help a lot of people who don’t know all the niche information about it. :slight_smile:

3 Likes

I believe yes, this is the only option out there, as I am still searching, if I find another way I’ll reply here, if I don’t get back here, that means there is no other way to do it.