Let's say I have a label which grows vertically to fit texts of different length - for example, item descriptions. Anchored to the label, there is a widget offset by, say, -24 on the left, 24 on the right, 24 on the top, -24 on the bottom. In turn, anchored to the top, left and right (never bottom) of that widget are various secondary child elements, like a clamped header with an item name, item preview images, fixed-size lines with item stats and so on. To illustrate, here is how this looks:
Game camera view:Scene view of the primary label and sole widget directly parented to it:Scene view of the secondary elements anchored to the boundary widget:There is a small problem with that sort of setup. While it works like you see on the gifs in Edit mode, Play mode is a different story. Unless you make set every single anchor to OnUpdate refresh mode (which you definitely don't want to do if you want to avoid GC from anchoring operations generated every frame), there is no way to actually force a refresh on all those elements after you change the text on that label. I've tried a lot of methods exposed by NGUI UIPanel and looked at how on-anchor refreshing is done in UIRect/UIWidget/UIPanel and I think there is no standard way to do that for OnEnable/OnStart anchors.
Please correct me if I'm wrong and actually missed some method on UIPanel or other NGUI class meant to force refresh of all anchored widgets. I went on with an assumption that no such method exists and tried to force it manually, with my own methods. I focused on an attempt to devise a method that would force correctly ordered anchor refresh on every single widget under a certain panel - while forcing an anchoring update of an individual widget is easy, it's not a useful approach, since it would require every anchoring-influencing object to keep explicit references to all anchored dependent objects. I just wanted to call something like panel.ForceAnchorRefresh () from my label, which keeps the UI nicely decoupled. Here is what I got:
public void ForceAnchorRefresh ()
{
ForceAnchorRefreshRecursive (transform);
}
private void ForceAnchorRefreshRecursive (Transform parent)
{
UIRect rect = parent.GetComponent<UIRect> ();
if (rect != null)
rect.UpdateAnchors ();
for (int i = 0; i < parent.childCount; ++i)
ForceAnchorRefreshRecursive (parent.GetChild (i));
}
This works great, with sole exception of cases where widgets influencing other widgets but not being their parents aren't guaranteed to update first. But that's easy to prevent if you structure your UI with strict parenting reflecting anchoring dependencies. Is there anything wrong with this approach, or it's a sound way to force refresh of OnStart/OnEnable anchored widgets after their dependency was resized?