GridFrameLayout Dynamic Column Sizing: How isAutoSize Manages Adaptive Layouts in FrameLayoutKit
When isAutoSize is enabled in GridFrameLayout, the arrangeViews(autoColumns:) method dynamically calculates either row or column counts based on the layout axis, using ceil(viewCount / fixedDimension) to ensure all child views fit within the specified constraints.
GridFrameLayout in the kennic/framelayoutkit repository provides a flexible grid system for iOS development. When the isAutoSize property is enabled, the layout engine automatically adjusts column or row counts to accommodate varying numbers of child views without manual recalculation.
Core Auto-Size Logic in arrangeViews(autoColumns:)
The dynamic sizing implementation resides in GridFrameLayout.swift within the arrangeViews(autoColumns:) method. This routine serves as the central layout coordinator, invoked whenever the view hierarchy changes, when the view's size changes, or when isAutoSize is toggled.
When isAutoSize evaluates to true, the method branches based on the current axis property:
func arrangeViews(autoColumns: Bool = true) {
guard viewCount > 0 else { return }
var numberOfRows = stackLayout.frameLayouts.count
if isAutoSize {
// Horizontal axis – compute rows from the fixed column count
if axis == .horizontal, columns > 0 {
let fitRows = max(Int(ceil(Double(viewCount) / Double(columns))), 1)
if fitRows != rows {
rows = fitRows // updates rows → triggers layout
numberOfRows = fitRows
}
}
// Vertical axis – compute columns from the fixed row count
else if axis == .vertical, rows > 0 {
let fitColumn = max(Int(ceil(Double(viewCount) / Double(rows))), 1)
if fitColumn != columns {
columns = fitColumn // updates columns → triggers layout
}
}
}
// ...
}
Source: [GridFrameLayout.swift, lines 33-48](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/GridFrameLayout.swift#L33-L48)
Axis-Dependent Dynamic Sizing
The GridFrameLayout adapts its calculation strategy based on whether the layout flows horizontally or vertically.
Horizontal Axis: Dynamic Row Calculation with Fixed Columns
When axis is set to .horizontal and isAutoSize is enabled, the columns property remains fixed (either as specified by the developer or defaulting to 0). The layout engine calculates the required number of rows using ceiling division:
let fitRows = max(Int(ceil(Double(viewCount) / Double(columns))), 1)
This ensures that all child views fit within the specified column count, adding rows as necessary when the view count increases.
Vertical Axis: Dynamic Column Sizing with Fixed Rows
Conversely, when axis is .vertical, the rows property remains fixed while the system dynamically calculates the column count:
let fitColumn = max(Int(ceil(Double(viewCount) / Double(rows))), 1)
This mode is particularly useful for creating horizontally scrolling grids or adaptive flow layouts where you want to maintain a specific row height while allowing columns to expand based on content.
Width-Based Column Optimization Using maxColumnWidth
Beyond the basic isAutoSize functionality, GridFrameLayout supports dynamic column sizing based on available width through the maxColumnWidth property. When this property is non-zero and autoColumns remains true, the layout recalculates how many columns fit into the current bounds:
if axis == .horizontal {
if autoColumns, maxColumnWidth > 0 {
var viewSize = stackLayout.bounds.size
if viewSize == .zero { viewSize = bounds.size }
// Compute how many columns fit into the current width
let fitColumns = max(Int(viewSize.width / maxColumnWidth), max(initColumns, 1))
if columns != fitColumns {
columns = fitColumns // triggers a second arrange pass
arrangeViews(autoColumns: false) // re-layout with the new column count
return
}
}
// ...
}
Source: [GridFrameLayout.swift, lines 52-60](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/GridFrameLayout.swift#L52-L60)
This mechanism works in conjunction with isAutoSize to provide responsive grid layouts that adapt to both content count and container width.
Layout Trigger Points and Update Mechanisms
The dynamic sizing system responds to several trigger points defined in GridFrameLayout.swift:
Size Change Detection
The layoutSubviews() override monitors bounds changes when maxColumnWidth is active:
if maxColumnWidth > 0, lastSize != bounds.size {
lastSize = bounds.size
arrangeViews()
}
Source: [GridFrameLayout.swift, lines 7-10](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/GridFrameLayout.swift#L7-L10)
Property Observers
Changes to isAutoSize, axis, rows, columns, maxColumnWidth, or the underlying views array automatically invoke arrangeViews() through their didSet observers, ensuring the layout remains synchronized with state changes without manual intervention.
Summary
arrangeViews(autoColumns:)serves as the central layout coordinator inGridFrameLayout.swift, implementing all dynamic sizing logic.- When
isAutoSizeis enabled, the layout calculates missing dimensions usingceil(viewCount / fixedDimension)to ensure complete view coverage. - Horizontal axis layouts fix the column count and compute rows dynamically, while vertical axis layouts fix the row count and compute columns dynamically.
- The
maxColumnWidthproperty enables width-responsive column calculation, triggering secondary layout passes when container bounds change. - Layout updates occur automatically through
layoutSubviews()overrides anddidSetproperty observers on key configuration properties.
Frequently Asked Questions
What happens when isAutoSize is disabled in GridFrameLayout?
When isAutoSize is set to false, GridFrameLayout respects the explicit rows and columns values set by the developer without automatic calculation. The arrangeViews method skips the dynamic sizing logic, using only the predefined grid dimensions to position child views, which may result in empty cells or clipped content if the view count exceeds the fixed grid capacity.
How does GridFrameLayout handle device rotation with dynamic column sizing?
During device rotation or any bounds change, GridFrameLayout detects size changes in layoutSubviews() when maxColumnWidth is active. The method compares lastSize against bounds.size and invokes arrangeViews() to recalculate the column count based on the new width. This ensures the grid adapts responsively to orientation changes while maintaining the maximum column width constraint.
Can I use both maxColumnWidth and isAutoSize simultaneously?
Yes, these properties work complementarily. When both are enabled, isAutoSize first calculates the required rows or columns based on view count and axis direction. Subsequently, if maxColumnWidth is set and autoColumns remains true, the layout performs a secondary calculation to determine how many columns fit within the available width. This two-phase approach allows the grid to adapt to both content quantity and container dimensions.
What is the difference between horizontal and vertical axis behavior in auto-size mode?
In horizontal axis mode with isAutoSize enabled, the columns property remains fixed (as specified by the developer) and the system dynamically calculates the required rows using ceil(viewCount / columns). Conversely, in vertical axis mode, the rows property remains fixed while the system dynamically calculates the columns needed to display all views using ceil(viewCount / rows). This axis-dependent behavior determines whether the grid expands vertically or horizontally to accommodate content.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →