Class FlexContainer
Flexbox implementation as per CSS3 (https://www.w3.org/TR/css-flexbox-1/#box-model): the FlexContainer holds 0 or more child FlexItems, and arranges them according to the Flexbox layout settings. Child FlexItems can also be FlexContainers themselves, in which case each child will layout its own children.
Note: a FlexContainer will not perform any layout unless it is part of a RootFlexContainer.
Generally you create a layout by doing the following steps:
- Choose a RootFlexContainer or FlexContainer you've already configured
- Add a new child with both a FlexItem (to control how the parent RFC/FC lays it out) and a FlexContainer (for you to apply new layout settings)
- Add to your new FlexContainer as many child objects as you need, with a FlexItem on each
- Choose the layout settings on your new FlexContainer
Creating from script
Recommended to use CreateFlexComponents which simplifies the creation/adding of new instances
Sizing
FlexContainers do not have any control over their own size: they require an attached FlexItem, and a parent FlexContainer (or RootFlexContainer) - the parent then decides what size this FlexContainer should be.
Sizing and Positioning children
FlexContainers perform all the sizing AND positioning of their direct children. Only children with a FlexItem component are affected - all others are ignored. If you remove the FlexItem from a child it will become effectively invisible to Flexbox and will only be sized by Unity's in-built UI (if at all).
The FlexContainer uses its local LayoutAlgorithm to perform the actual layout. The local LayoutAlgorithm is currently set by the first parent RootFlexContainer, and all FlexContainers embedded in that RootFlexContainer share the same LayoutAlgorithm.
CSS3 Settings
The primary settings from the CSS3/Flexbox specification that control layout of a FlexContainer are:
Implements
Inherited Members
Namespace: NinjaTools.FlexBuilder
Assembly: cs.temp.dll.dll
Syntax
public class FlexContainer : BFlexComponent, IFlexComponent, IUpgradeableComponent, ILayoutGroup, ILayoutElement
Fields
- (Boolean) blockNextOnDisableCall
- (Boolean) blockNextOnEnableCall
- (FlexContainerEvent) OnAnyLayoutHappened
Invoked whenever ANY layout of this container is completed -- this automatically aggregates all of OnFullLayoutHappened, OnPartialLayoutRepositionedChildren and OnPartialLayoutChildrenNotSelf
- (FlexContainerEvent) OnFullLayoutHappened
Invoked whenever a full layout of this container is completed
- (FlexContainerEvent) OnPartialLayoutChildrenNotSelf
Invoked when a partial layout is completed: full layout of children (sizes + positions) but the container itself didn't recalculate its size
- (FlexContainerEvent) OnPartialLayoutRepositionedChildren
Invoked when a partial layout is completed: the children were repositioned but not resized
- (Boolean) requiresRelayout
Used by v4 LayoutAlgorithms to decide which FlexContainers can be skipped/re-used during a Relayout operation
- (Boolean) showDebugMessages
Properties
- (AlignContent) alignContent
- (AlignItems) alignItems
- (List<FlexItem>) childFlexItems
- (List<FlexItem>) childFlexItems_Ordered
This performs the CSS3 sorting, using z-order combined with UnityUI Transform order, to get the ACTUAL order of child FlexItems that the Flexbox algorithm will use.
- (Single) columnGap
Specification: https://drafts.csswg.org/css-align/#propdef-column-gap
"When applied to the main axis (e.g. column-gap in a row flex container), indicates minimum spacing between items (as if an additional fixed-size margin were inserted between adjacent flex items in a single line)."
- (RectTransform.Axis) crossAxis
- (Boolean) debugRelayout_StackOnly
- (List<FlexContainer>) descendantFlexContainers
Finds all FlexContainers in the tree below this point BUT STOPS when it hits a leaf node - this is especially important if your tree contains a leaf, that contains a scrollrect, that has an embedded RootFlexContainer.
i.e. ONLY sends FlexContainers controlled by the same RootFlexContainer that contains this FlexContainer.
- (FlexDirection) direction
- (Single) flexibleHeight
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (Single) flexibleWidth
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (Single) gapWidthInCross
- (Single) gapWidthInMain
- (Boolean) isAxisReversed
- (FlexJustify) justifyContent
- (Int32) layoutPriority
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (RectTransform.Axis) mainAxis
- (Single) minHeight
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (Single) minWidth
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (HierarchyObjectType) parentObjectType
- (Single) preferredHeight
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (Single) preferredWidth
UnityUI built-in property that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (Single) rowGap
Specification: https://drafts.csswg.org/css-align/#propdef-row-gap
"When applied to the cross axis (e.g. row-gap in a row flex container), indicates minimum spacing between adjacent flex lines."
- (IFlexboxLayoutAlgorithm) sharedLayoutAlgorithm
Convenience getter for reading the containing RootFlexContainer's algorithm (which is shared by everything in the tree)
- (ITreeUpdateAlgorithm) sharedTreeAlgorithm
Convenience getter for reading the containing RootFlexContainer's algorithm (which is shared by everything in the tree)
- (List<FlexItem>) Spec_9_1_1_sortedChildFlexItems
Spec: https://www.w3.org/TR/css-flexbox-1/#order-property
With Flexbox, you MUST ALWAYS pre-sort FlexItems using their .order property - NB: even in 2022 Unity has failed to honour this part of the spec with their UIToolkit implementation -- i.e. 4 years after launch they are still failing in a core feature.
This method sorts the direct FlexItem children according to Order (spec says: sort each flexOrder as a complete group), but defaulting to Transform order where .order values are identical
- (Version) versionCreatedBy
Overrides
- (Version) versionUpgradedTo
Overrides
- (FlexWrap) wrap
Methods
- (void)
ApplyToChildFlexItems(Action)
- (void) CalculateLayoutInputHorizontal()
UnityUI built-in method that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (void) CalculateLayoutInputVertical()
UnityUI built-in method that is completely disabled by Flexbox, in favour of the faster and more accurate Flexbox algorithm
- (void) Clear()
Fast, efficient, way to remove all child FlexItems/FlexContainers from this FlexContainer, with virtually no GC overhead (bypasses a lot of internal checks and balances which aren't needed because we know we're destroying the child items) - NOTE: This can be typically 1000x or more faster than your own code for 'clearing' a RectTransform
- (Single) CurrentInnerLength(RectTransform.Axis)
CSS defines 'inner size' as 'content (NO padding, NO border, NO margins)'.
This method SHOULD NOT be used during a layout operation / by a layout algorithm! It is only valid/correct after layout has completed and imposed a specific size on this FlexContainer, and then this method INFERS the EFFECTIVE/USED outer-size based on looking at the current literal Unity3D size.
Parameters
RectTransform.Axis | axis |
Returns
Single | Inner size in the specified dimension, as defined by CSS |
- (Single)
CurrentOuterLength(Nullable, RectTransform.Axis)
CSS defines 'outer size' as 'content + padding + border + margins)'.
This method SHOULD NOT be used during a layout operation / by a layout algorithm! It is only valid/correct after layout has completed and imposed a specific size on this FlexContainer, and then this method INFERS the EFFECTIVE/USED outer-size based on looking at the current literal Unity3D size.
Parameters
Nullable<Single> | parentInnerLength | |
RectTransform.Axis | axis |
Returns
Single | Inner size in the specified dimension, as defined by CSS |
- (Nullable<Single>)
definiteInnerCrossLength(Nullable)
- (Single) innerCrossSize(Single)
- (Vector2) innerSize(Vector2)
Parameters
Vector2 | selfSize |
Returns
Vector2 |
- (void) OnDisable()
- (void) OnEnable()
- (void) OnEnable_ConsiderRelayouting()
Unity has a major bug: there is literally no way to know if OnEnable is being caused INSIDE an Instantiate call (at which time, by definition, Unity does not allow the MonoBehaviour to be fully valid), or if it's being called because the MonoBehaviour has been enabled - this is a bug they designed-in and completely failed to provide any workarounds for.
This is worse because Unity also has major design mistake: it is impossible to instantiate a MonoBehaviour if that has any important parameters -- Unity removed the core concept of 'Constructors' from the C# language rather than implement their Serializer correctly.
This method is invoked during OnEnable, after any internal checks and performance tweaks have been done to filter-out 'definitely ignorable' OnEnable calls. What is left is situations where 'potentially' a relayout is needed; this method processes those situations and decides what to do
For FlexContainer:
- we check whether this component is already inside a FlexboxContext (i.e. a chain that terminates in a RootFlexContainer at the top of the hierarchy) -- and if not, we skip doing the layout
- (void) OnFlexPropertyModified(String)
Called by internal methods any time a property of this FlexContainer is changed, so that a layout can automatically be scheduled.
TODO: In v4 onwards I aim to make all FlexItem, FlexContainer, properties auto-layout-triggering, so that this method NEVER needs to be called (except as a potential performance optimization, where you disable this auto triggering until end of frame, then manually trigger one call per object, rather than N calls per object)
Parameters
String | propertyName |
- (void) OnRectTransformDimensionsChange()
We override this to disable it; this is the only FULLY WORKING way to prevent bugs in Unity's UI system from causing incorrect layout calls, while still preserving the callbacks for correct layout calls (Unity's implementation of UIBehaviour and ILayoutGroup etc has never WORKED, and instead of fixing the bugs they gave up and started work on UIToolkit, which has even more bugs and problems).
Flexbox will NEVER trigger this callback: we circumvent it ... so if this callback DOES fire, that means it's being fired by Unity, and we can deduce that it's a 'change' we want to block and/or re-instate the correct / cached values of the layout tree.
Unity's description: "This callback is called if an associated RectTransform has its dimensions changed."
- (void) OnTransformChildrenChanged()
- (void) Reset()
NOTE 1: Bug in the UnityEditor: this method WILL NOT BE CALLED if the Editor is in PlayMode, even though the contents of the method are essential to maintain data-integrity (this method is the ONLY method that Unity officially provides for implementing the callback "Component Was Added To GameObject").
NOTE 2: Bug in Unity: Unity broke their build-system if you use Reset() or OnValidate() on any UIBehaviour subclass. I don't know why Unity did this, there are no comments in the source code, and no explanation in the docs - they just appear to have had no idea what they were doing.
(The UnityEditor DLL and the UnityEngine DLL have incompatible definitions of those methods - which should not be possible!) The workaround we use for now:
- For source builds, we default to doing it correctly (IF UNITY_EDITOR will always be true)
- DLL builds of the project (e.g. the free LITE version) need special multiple DLLs of same name, but different asmdef 'compile for platform' settings