Uniformed UI scaling question

How do I keep my UI looking similar to this, where the icon is on the left side of the frame and on the right is the text, when scaling?

Currently when I make the UI taller, it looks like this, where the text is clipping over the icon:

But I want it to look more like the first image. I understand that this is caused by the icon’s SizeConstraint being set to RelativeYY, which makes the icon bigger depending on the height of the frame (which is what I want), but how do I offset the texts position/scale to accommodate the larger icons? I can’t exactly make the TextLabel SizeConstraint also be RelativeYY because I want to make sure it fills up the remaining horizontal space in the frame… Soo, what do I do?

3 Likes

You can take several measures to prevent this from happening:

  1. I know that RelativeYY is what you need, but unless it is absolutely necessary, try using RelativeXX (or as an alternative, you can use a UIAspectRatioContraint with a DominantAxis of “Width”).

  2. To position the text elements based on the size of the gun icon, you can simply make the text a child of the icon. Then, you can set the position of the X scale to 1 so that the text is always to the right of the square icon.

  3. You can use a script that will check if the AbsoluteSize of the icon changes, then using the AbsoluteSize, you can set the text elements’ X size to the AbsoltueSize of the parent minus the AbsoluteSize of the icon. You can also add in a margin there if you want. Here is a code sample with the margin included:

     local frame = script.Parent --the green container behind
     local icon = frame.Icon --the gun icon
     local text = frame.Text --one of the text elements
     local margin = 0.05 --optional, but needed if you want this to look neat
     local mouse = game.Players.LocalPlayer:GetMouse()
     local x = mouse.ViewSizeX
    
     local function adjust()
     	
     	text.Size = UDim2.new(0, frame.AbsoluteSize - (icon.AbsoltueSize + (margin * x)), 0.1, 0) --[[0.1 is just an example, the Y can be
     	anyhing really. Also, the expression here needs to be in the offset part of the X size property, because we are working 
     	with AbsoluteSize which are in pixels]]
     	
     end
    
     adjust() --need to call this initially, before the size changes
    
     icon:GetPropertyChangedSignal("AbsoluteSize"):Connect(adjust) --use AbsoluteSize because this updates when the parent/frame's size changes, unlike the UDim2 Size property
    

Hopefully, one of these steps would work for you.

1 Like

This can be done, but beware the size of the TextLabels will need to be updated to keep them from going outside of the frame (unless you have a constant AspectRatio, which I do recommend so perhaps this point is moot). An alternative method is putting in a UIListLayout which will do the same thing without the reparenting.

Yup this is pretty much the only proper way to do it :slight_smile: Wish we a built-in feature for this sort of behavior. It is possible to emulate this somewhat with UITableLayout, but then it becomes unnecessarily complicated with too many redundant objects.

Also small tip on your code: you can just do signal:Connect(adjust) instead of signal:Connect(function() adjust() end). You’d only want to do the latter if you needed to call the function with arguments that aren’t being supplied by the signal :wink: In this case there are no supplied arguments and the function doesn’t require any arguments so we don’t need to wrap it in another function.

2 Likes