PixelRows.luau
Luau, 61 lines from UI overview
--!strict
-- PixelRows: size ScrollingFrame rows in PIXELS worked out from the list's own height.
-- Inside a ScrollingFrame, a child's Scale size resolves against the CANVAS. With
-- AutomaticCanvasSize the canvas is measured from the children, so Scale rows and the canvas define
-- each other: rows collapse (scale*count < 1), explode (> 1, seen at 112 million px), or settle at
-- an arbitrary size. Pixel rows break the loop; AutomaticCanvasSize then just follows content.
local PixelRows = {}
-- list: the ScrollingFrame. visible: how many rows should fit in the window. gap: px between rows.
function PixelRows.bind(list: ScrollingFrame, visible: number, gap: number): () -> ()
local layout = list:FindFirstChildOfClass("UIListLayout") or Instance.new("UIListLayout")
layout.SortOrder = Enum.SortOrder.LayoutOrder
layout.Padding = UDim.new(0, gap) -- Offset, never Scale, for the same reason as the rows
layout.Parent = list
list.AutomaticCanvasSize = Enum.AutomaticSize.Y
list.CanvasSize = UDim2.new(0, 0, 0, 0)
local function apply()
local h = list.AbsoluteSize.Y
if h <= 0 then return end
local rowH = math.floor((h - gap * (visible - 1)) / visible)
for _, row in list:GetChildren() do
if row:IsA("GuiObject") then
row.Size = UDim2.new(1, -list.ScrollBarThickness, 0, rowH)
end
end
end
local conns = {
list:GetPropertyChangedSignal("AbsoluteSize"):Connect(apply), -- still adapts to screen size
list.ChildAdded:Connect(function() task.defer(apply) end),
}
apply()
return function()
for _, c in conns do c:Disconnect() end
end
end
-- Audit any pasted UI kit: flags Scale-sized rows inside ScrollingFrames and Scale CanvasSize.
function PixelRows.audit(root: Instance): { string }
local out = {}
for _, d in root:GetDescendants() do
if d:IsA("ScrollingFrame") then
if d.CanvasSize.Y.Scale > 1.01 then
table.insert(out, d:GetFullName() .. ": CanvasSize.Y.Scale = " .. d.CanvasSize.Y.Scale)
end
for _, c in d:GetChildren() do
if c:IsA("GuiObject") and c.Size.Y.Scale > 0 then
table.insert(out, c:GetFullName() .. ": row height is Scale " .. c.Size.Y.Scale)
break
end
end
end
end
return out
end
return PixelRows