Automatic Canvas size not working

yes automaticcanvas is enabled but when I change the text, the canvas doesn’t expand

Hmm. I went ahead and tested it out with the same setup. It works for me.
Textbox Test

here is a video


it stops when the canvas is full and doesn’t expand

The textbox has AutomaticSize enabled?

yes it does
image
also textwrapped

did you use AbsoluteSize here?

TextWrapped is what is causing the issues if I had to guess. Textwrap cuts off any text that doesn’t fit within its bounds, thus not allowing AutomaticSize to trigger properly. Try it without text wrapping.

I disabled textwrapped and this happened,

edit: I also tried setting the frame’s scrolling direction to y only and it still doesn’t work

edit again: also in the developer wiki, it says that text wrapped should be enabled when automatic size is set to y

can you try recreating it again but with y scrolling instead of x?

Yeah. That’s correct. It should be that way but this is some weird behavior.
The issue is that with TextWrapped enabled, it will not allow AutomaticSize to be larger than its Parent AbsoluteSize.
This might need a custom solution/workaround. Lemme see if I can figure out one.

1 Like

I think I found the problem. Your code is actually expanding the scrolling frame’s Y offset canvas size, but the text box is using scale, so I tried it with TextWrapped enabled and then changed something in the code.

so it would edit the offset instead,

then I tried it and this happened

the canvas expands too much, as you can see in the scroll bar (maybe because offset and scale works differently, so it should expand to the perfect size with the right formula)

but another problem showed up, it’s that the text box also stopped when it reached the size of the original canvas. the canvas was still expanding when i’m typing more texts, but the text box automatic size doesn’t work

edit: I changed these from offset to scale

image

edit again: it’s still doing the same thing (expanding too big)

Yeah, the canvas is supposed to work like that. The AutomaticCanvasSize should have its Offset the same as it’s content AbsoluteSize. It’s set to Offset instead of Scale for a reason. The only time you should use scale is when trying to multiply how much bigger you want it to be. The padding variables are used to account UIPadding Offsets. Because I was just using it as a personal workaround and wasn’t using UIPadding Scale, I didn’t include anything for UIPadding Scale.

You noted that the text box also stopped when it reached the size of the original canvas. That’s not why its doing that. Like I said previously,

Its dependent on it’s Parent AbsoluteSize not AbsoluteCanvasSize.

So do I need to do the textbox sizing manually?

Here is the workaround I conjured up. This isn’t perfect (it can miss fast typed text) but I hope that it will suffice.

You’ll need to make sure that TextWrapped is disabled, this “should” do the text wrapping for you since Roblox’s own TextWrapping doesn’t work properly with AutomaticSize. If this doesn’t work, I don’t know if I can come up with anything better.

local function UpdateSize(FrameInstance,LayoutInstance)
	if FrameInstance and LayoutInstance then
		local PaddingX = 0
		local PaddingY = 0
		if FrameInstance:FindFirstChildOfClass("UIPadding") then
			local UIPadding = FrameInstance:FindFirstChildOfClass("UIPadding")
			PaddingX += UIPadding.PaddingLeft.Offset
			PaddingX += UIPadding.PaddingRight.Offset
			PaddingY += UIPadding.PaddingBottom.Offset
			PaddingY += UIPadding.PaddingTop.Offset
		end
		if FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.Y then
			FrameInstance.CanvasSize = UDim2.new(0,0,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
		elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.X then
			FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,0)
		elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.XY then
			FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
		end
	end
end


local v = script.Parent
local Layout = v:FindFirstChildOfClass("UIListLayout") or v:FindFirstChildOfClass("UIGridLayout")
local TextBox = script.Parent.TextBox
TextBox:GetPropertyChangedSignal("AbsoluteSize"):connect(function() UpdateSize(v,Layout) end)
local LastAdjustedAWholeWord = ""
TextBox:GetPropertyChangedSignal("TextFits"):Connect(function()
	local LP = game.Players.LocalPlayer
	if TextBox.TextFits == false then
		local OldText = TextBox.Text
		local TextAdjustment = 1
		TextBox.TextEditable = false
		TextBox:ReleaseFocus()
		repeat
			local RevString = string.reverse(TextBox.Text)
			local NewString = ""
			if RevString:find(" [%C]") and (RevString:sub(1, RevString:find(" [%C]", TextAdjustment)):find(LastAdjustedAWholeWord) == nil or LastAdjustedAWholeWord == "") then
				LastAdjustedAWholeWord = RevString:sub(1, RevString:find(" [%C]", TextAdjustment))
				NewString = RevString:sub(1, RevString:find(" [%C]", TextAdjustment)) .."\n" ..  RevString:sub(RevString:find(" [%C]", TextAdjustment)+1, RevString:len())
			else
				NewString = RevString:sub(1, RevString:find("%C", TextAdjustment)) .."\n" ..  RevString:sub(RevString:find("%C", TextAdjustment)+1, RevString:len())
			end
			TextBox.Text = string.reverse(NewString)
			TextAdjustment+=1
			wait()
		until TextBox.TextFits == true
		TextBox.TextEditable = true
		TextBox:CaptureFocus()
	end
end)

This might behave weird or improperly when pasting long texts and/or typing fast. Like I said this is a workaround, not a solution. Roblox needs to fix their Gui problems on their own. It’s been lacking proper support for years, they add new features but don’t adapt the rest of it to be properly compatible. Still waiting on Roblox for proper rotation support (Antialiasing, AnchorPoints that respect rotation, etc.) :weary:

Yeah, I wouldn’t rely on this. It kinda doesn’t work for editing the middle of text… Hmmmmmmm

what do you mean?

asd

It bugs out when adding text to anywhere that isn’t at the end.

oh, is there anything I can do to fix it?

Here is a fix. This works around the issue of AutomaticSize being constrained to its Parent size with TextWrapping enabled. Its basically just a manual AutomaticSize.

local AutoScrollToBottomY = true
local ScreenGUI = script.Parent.Parent.Parent
local AllChildren = ScreenGUI:GetDescendants()
for i,v in pairs (AllChildren) do 
	if v:IsA("ScrollingFrame") then 
		if v:FindFirstChildOfClass("UIListLayout") or v:FindFirstChildOfClass("UIGridLayout")then
			local Layout = v:FindFirstChildOfClass("UIListLayout") or v:FindFirstChildOfClass("UIGridLayout")
			local function UpdateSize(FrameInstance,LayoutInstance)
				if FrameInstance and LayoutInstance then
					local PaddingX = 0
					local PaddingY = 0
					if FrameInstance:FindFirstChildOfClass("UIPadding") then
						local UIPadding = FrameInstance:FindFirstChildOfClass("UIPadding")
						PaddingX += UIPadding.PaddingLeft.Offset
						PaddingX += UIPadding.PaddingRight.Offset
						PaddingY += UIPadding.PaddingBottom.Offset
						PaddingY += UIPadding.PaddingTop.Offset
					end
					if FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.Y then
						FrameInstance.CanvasSize = UDim2.new(0,0,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
					elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.X then
						FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,0)
					elseif FrameInstance.AutomaticCanvasSize == Enum.AutomaticSize.XY then
						FrameInstance.CanvasSize = UDim2.new(0,LayoutInstance.AbsoluteContentSize.X + PaddingX,0,LayoutInstance.AbsoluteContentSize.Y + PaddingY)
					end
					if AutoScrollToBottomY then
						v.CanvasPosition = Vector2.new(0,v.AbsoluteCanvasSize.Y - v.AbsoluteWindowSize.Y)
					end
				end
			end
			UpdateSize(v,Layout)
			Layout.Changed:connect(function() UpdateSize(v,Layout) end)
			v:GetPropertyChangedSignal("AutomaticCanvasSize"):connect(function() UpdateSize(v,Layout) end)
		end
	end
end

for i,v in pairs (AllChildren) do
	if( v:IsA("TextBox") or v:IsA("TextLabel") or v:IsA("TextButton") ) and v:GetAttribute("CustomAutoSizeY") == true then
		local TextBox = v
		local Spacing = 1.20
		TextBox.TextWrapped = true
		if v.AutomaticSize == Enum.AutomaticSize.Y then
			v.AutomaticSize = Enum.AutomaticSize.None
		elseif v.AutomaticSize == Enum.AutomaticSize.XY then
			v.AutomaticSize = Enum.AutomaticSize.X
		end
		local XScale = TextBox.Size.X.Scale
		TextBox.Size = UDim2.new(XScale,0,0,TextBox.TextSize*Spacing)
		local NumberOfLines = 1
		local AdjustingSize = false
		local function AdjustTextBoxSize()
			AdjustingSize = true
			TextBox.Size = UDim2.new(XScale,0,0,(TextBox.TextSize*Spacing)*NumberOfLines)
			AdjustingSize = false
		end
		TextBox:GetPropertyChangedSignal("Text"):Connect(function()
			if TextBox.TextFits == false and AdjustingSize == false then
				NumberOfLines += 1
				AdjustTextBoxSize()
			end
		end)
		local OldText = TextBox.Text
		local OriginalName = TextBox.Name
		TextBox.Name = "ScriptRelocatingThisInstance"
		local TextBoxParentClone = TextBox.Parent:clone()
		for i,v in pairs(TextBoxParentClone:GetDescendants()) do
			if v:IsA("Script") or v:IsA("LocalScript") then
				v.Disabled = true
				v:Destroy()
			end
		end
		TextBoxParentClone.Visible = false
		TextBoxParentClone.Name = TextBox.Parent.Name.."(ScriptClone)"
		TextBoxParentClone.Parent = TextBox.Parent.Parent
		local TextBoxClone = TextBoxParentClone:FindFirstChild("ScriptRelocatingThisInstance")
		if not TextBoxClone then error("Could not find clone for textbox.") end
		TextBox.Name = OriginalName
		local TestingSize = false
		TextBox:GetPropertyChangedSignal("Text"):Connect(function()
			TextBoxClone.Text = TextBox.Text
			TextBoxClone.Size = UDim2.new(XScale,0,0,(TextBox.TextSize*Spacing)*NumberOfLines)
			if TextBox.Text:len() < OldText:len() and TestingSize == false  and TextBoxClone.TextFits == true then
				TestingSize = true
				local OldTextCapture = OldText
				local ProperFit = NumberOfLines
				for i = 1, NumberOfLines do
					TextBoxClone.Size = UDim2.new(XScale,0,0,((TextBox.TextSize*Spacing)*(NumberOfLines-i) ) )
					if TextBoxClone.TextFits == false then
						ProperFit = NumberOfLines - (i-1)
						break
					end
					--wait()
				end
				if ProperFit ~= NumberOfLines then
					NumberOfLines = ProperFit
					AdjustTextBoxSize()
				end
				TestingSize = false
			end
			OldText = TextBox.Text
		end)
	end
end
6 Likes

To make TextLabel work with AutomaticCanvasSize you need to set “RichText” property to true.
I dissapointed that it isn’t fixed yet.

7 Likes