I’m currently experimenting with making and scripting shop UI for a game. The UI is currently color-coded in bright colors in order to differentiate sections of the UI for debugging:
The blue section of the shop is a description bar that’s meant to display a text description of whatever item you’ve selected by clicking a button that appears in the green section. The description (not including the ImageLabel above it) is basically a ScrollingFrame with a TextLabel inside of it. I need the ScrollingFrame’s CanvasSize to change based on how much space the text inside of it is taking up, such that if the text starts to run off the bottom of the UI, the CanvasSize expands so that you can scroll down and still read it.
The ScrollingFrame has a CanvasSize of {0, 0}, {0, 0}, and its AutomaticCanvasSize = Y.
The TextLabel has a Size of {1, 0}, {0, 0}, and its AutomaticSize = Y. TextScaled = false, TextWrapped = true.
According to what I’ve read, this should be enough— but it isn’t. The text is meant to read “…clicking the X after talking to a shopkeeper”, but it still gets cut off at the bottom despite these settings. Supposedly having an AutomaticSize of Y for the TextLabel should make it scale based on the size of its text, but instead it just seems to make it scale to fill the size of the ScrollingFrame, which isn’t what I want. What do I have to change to make this work? Is a custom script necessary?
I’m setting the X scale to 1 so that it fills the ScrollingFrame. UDim2.new() has xScale, xOffset, yScale, yOffset. Even if I was setting the Y scale instead of the Y offset, wouldn’t it be like 32 times the size of the ScrollingFrame? Or are you referring to something else?
local function Update():()
print("The TextBounds changed to", scrollingFrame.TextLabel.TextBounds)
scrollingFrame.TextLabel.Size = UDim2.new(1,0, 0,scrollingFrame.TextLabel.TextBounds.Y)
end
scrollingFrame.TextLabel:GetPropertyChangedSignal("TextBounds"):Connect(Update)
Update()
Oh wait- you actually did that right
Im sorry.
Well ig if i were to reply then i have to give some tip:
Wait you were not setting canvas size…
local TextLabel = scrollingFrame.TextLabel
local function Update():()
print("The TextBounds changed to", TextLabel.TextBounds)
scrollingFrame.CanvasSize = UDim2.new(1,0,0,TextLabel.TextBounds.Y)
end
TextLabel:GetPropertyChangedSignal("TextBounds"):Connect(Update)
Update()
I’m waiting to see if I can just let AutomaticCanvasSize deal with the scrolling part for me. If I understand it correctly, it should adjust it automatically according to the size of the TextLabel. What I’m having issues with right now is actually handling the TextLabel’s size. The official Roblox documentation makes it almost sound like TextBounds only detects the text that’s actually rendered, which means if the TextLabel isn’t already big enough, it gets cut off and then gets stuck…
Uh it should work for you, trust.
There is a mega hacky and semi broken way around TextService:GetTextSize(“TextHere”,20,TextLabel.Font,Vector2.new(math.huge,math.huge))
But i don’t recomend using this one.
Would using this work (assuming TextScaled is false)? You can get the height that the text needs to be in order to fit a certain width. It supports all fonts and rich text.
local textService = game:GetService('TextService')
local label = path.to.label
local scrollingFrame = label.Parent
local textBoundsParams = Instance.new('GetTextBoundsParams')
textBoundsParams.Font = label.FontFace
textBoundsParams.Size = label.TextSize
textBoundsParams.RichText = label.RichText
textBoundsParams.Width = label.Parent.AbsoluteSize.X
textBoundsParams.Text = label.Text
local ok, size = pcall(textService.GetTextBoundsAsync, textService, textBoundsParams)
if ok then
scrollingFrame.CanvasSize = UDim2.new(1, 0, 0, size.Y + 1) -- unsure if you need one pixel for padding on this method but I would add it to be safe
else
warn('Failed to get text bounds because', size)
scrollingFrame.CanvasSize = UDim2.new(1, 0, 0, label.TextSize * 30) -- some arbitrary size if this method fails
end
local Players = game:GetService("Players")
local scrollingFrame = script.Parent
local textLabel = scrollingFrame.TextLabel
local localPlayer = Players.LocalPlayer
local playerGui = localPlayer.PlayerGui
local shopGui = playerGui:WaitForChild("Shop")
local shopPanel = shopGui:WaitForChild("ShopPanel")
local SelectedItem = require(shopPanel.ActiveSelection)
local TextService = game:GetService("TextService")
local function resetDescription()
if not SelectedItem.CurrentItem then -- if no selection is made or an item is deselected
scrollingFrame.TextLabel.Text = "No item is selected..."
return
end
local item = SelectedItem.CurrentItem
local name = item.Name or "Unnamed item"
local price = item.Price or "???"
local description = item.Description or "Uh, there's no description for this item, sorry!"
scrollingFrame.TextLabel.Text = description
local descriptionSize = TextService:GetTextSize(description, textLabel.TextSize, textLabel.Font, Vector2.new(textLabel.Size.Width, math.huge))
print(descriptionSize)
scrollingFrame.TextLabel.Size = UDim2.new(1,0, 0,descriptionSize.Y)
end
shopGui.Events.NewSelection.Event:Connect(function()
resetDescription()
end)
I tried this but it keeps coming out to “(some number), 32” which is the TextSize of the TextLabel. I don’t know why it’s getting stuck at one line of text even when I’m telling it to assume there’s infinite Y space. I’m genuinely lost as to what to do now
Apparently this works??? Somehow??? I thought that the pcall(textService.GetTextBoundsAsync... thing would require a function call or something but that just ended up breaking it, tried it again exactly as you wrote and it started magically working. Could you please explain how that works?
textService.GetTextBoundsAsync is the reference to the function we want to call textService is the first argument (we pass this manually, when calling a function with a colon it implicitly passes whatever is before the colon as the first argument but in this case we have to pass it explicitly as we aren’t calling the function with a colon) textBoundsParams is the second argument