How can I make perfect scrolling frames?

Hey developers, I am trying to make a custom player list and I need the scrolling frame to perfectly fit all of its contents with no over scrolling and no under scrolling. Keep in mind I am doing this from a script so I can’t manually do this, I have also tried methods such as using the absolute content size property in UI constraints like mentioned here - Quick Tutorial: How to make scrolling frames properly - #4 by NinjoOnline but it doesn’t seem to work for me.

2 Likes

You could have it if it has max of 6 people in a server for example you could just do it without a scrolling frame. But if it hold more than about six then you would have to use a scrolling frame.

1 Like

You can use for that UIGridLayot (put it in your scrolling frame) and LocalScript (put it in UIGridLayout)

LocalScript

local ScrollingFrame = script.Parent.Parent

local function ChangeSize() 
	print("Changing size")
	
	local CellSize = script.Parent.CellSize
	local CellPadding = script.Parent.CellPadding
	local Children = #ScrollingFrame:GetChildren() - 1
	
	local X = ScrollingFrame.CanvasSize.X.Offset
	local Y1 = Children * CellSize.Y.Offset
	local Y2 = (Children - 1) * CellPadding.Y.Offset
	
	ScrollingFrame.CanvasSize = UDim2.new(0,X,0,Y1 + Y2)
end

ChangeSize()

ScrollingFrame.ChildAdded:Connect(ChangeSize)
ScrollingFrame.ChildRemoved:Connect(ChangeSize)

Edit: I improved the code and it works perfectly for me

1 Like

Yeah unfortunately my game is a story game and I am making the lobby which holds 40+ players.

1 Like

I will try this script a bit later, thanks for your help!

Edit: Is there a way to use this for UI list layouts instead of grid layouts?

Yes, but I think UIGridLayout is the best choise for you :grinning:

LocalScript (modified):

local ScrollingFrame = script.Parent.Parent

local function ChangeSize() 
	print("Changing size")

	local CellSize = UDim2.new(0,500,0,100) -- Change it on your own
	local Padding = script.Parent.Padding
	local Children = #ScrollingFrame:GetChildren() - 1

	local X = ScrollingFrame.CanvasSize.X.Offset
	local Y1 = Children * CellSize.Y.Offset
	local Y2 = (Children - 1) * Padding.Offset

	ScrollingFrame.CanvasSize = UDim2.new(0,X,0,Y1 + Y2)
end

ChangeSize()

ScrollingFrame.ChildAdded:Connect(ChangeSize)
ScrollingFrame.ChildRemoved:Connect(ChangeSize)

(Mark this as the solution if it helped)

2 Likes

Alternatively, you could use a function like this which is usable in any setting.

function calculateScrollFrameSize(scrollFrame, disableX)
    local maxX = -9999
    local maxY = -9999
    for _, obj in pairs(scrollFrame:GetDescendants()) do
	    if obj:IsA("GuiObject") and obj.Visible then
		    if (obj.AbsolutePosition.X + obj.AbsoluteSize.X) > maxX then
			    maxX = obj.AbsolutePosition.X + obj.AbsoluteSize.X
		    end
		    if (obj.AbsolutePosition.Y + obj.AbsoluteSize.Y) > maxY then
			    maxY = obj.AbsolutePosition.Y + obj.AbsoluteSize.Y
		    end
	    end
    end
    if disableX then
	    maxX = scrollFrame.AbsolutePosition.X
    end
    scrollFrame.CanvasSize = UDim2.new(0, maxX - scrollFrame.AbsolutePosition.X, 0, maxY - scrollFrame.AbsolutePosition.Y + 3)
end
2 Likes

I know you have your solution marked, but there’s a Property called AutomaticCanvasSize, which will automatically set the canvas size, based on contents of the scrolling frame

2 Likes