FrameLayoutKit heightRatio Property: Controlling Aspect Ratio and Intrinsic Size Behavior in Swift
The heightRatio property in FrameLayoutKit forces a view’s height to be a calculated multiple of its width, automatically disabling intrinsic height sizing whenever the ratio is greater than zero.
The heightRatio property is a core feature of FrameLayout (and its subclasses) in the kennic/framelayoutkit repository. It provides a declarative way to enforce fixed aspect ratios—such as 1:1 squares or 16:9 thumbnails—by overriding the target view’s intrinsic content size. When activated, the layout engine computes height dynamically from the final width, ensuring consistent proportions regardless of content changes.
What Is the heightRatio Property?
heightRatio is a CGFloat property defined on the FrameLayout class that expresses height as a multiplier of width.
- Default value:
0(disabled) - Active state: Any positive value (e.g.,
1.0,0.75,1.333) - Effect: When greater than zero, the layout ignores the target view’s intrinsic height and calculates
height = width × heightRatio
This mechanism is particularly useful for image views, video players, or card components where the aspect ratio must remain constant even when the container resizes.
How heightRatio Interacts with Intrinsic Size
The interaction between heightRatio and intrinsic sizing is governed by an automatic toggle in the property observer and conditional logic inside the layout engine.
Automatic Disabling of Intrinsic Size Mode
When you set a positive heightRatio, the property’s didSet observer automatically disables intrinsic-size mode to prevent conflicts. This is implemented in FrameLayoutKit/Classes/FrameLayout.swift (lines 46–52):
public var heightRatio: CGFloat = 0 {
didSet {
if heightRatio > 0 {
isIntrinsicSizeEnabled = false // Disables intrinsic height
}
}
}
By setting isIntrinsicSizeEnabled to false, the layout engine knows to ignore the target view’s intrinsicContentSize height and instead use the ratio-based calculation.
Size Calculation Logic in sizeThatFits
During layout, FrameLayout overrides sizeThatFits(_:) to apply the ratio constraint. The logic prioritizes heightRatio over intrinsic sizing, as shown in FrameLayout.swift (lines 82–88):
if heightRatio > 0 {
// Width is determined by intrinsic size (if enabled) or available space
result.width = isIntrinsicSizeEnabled ? contentSizeThatFits(size: contentSize).width
: contentSize.width
// Height is strictly derived from width using the ratio
result.height = result.width * heightRatio
} else {
// Standard intrinsic-size calculation when ratio is disabled
result = contentSizeThatFits(size: contentSize)
if !isIntrinsicSizeEnabled {
result.width = contentSize.width
}
}
When heightRatio is positive, the height becomes a deterministic function of the width, effectively locking the aspect ratio. When heightRatio is 0 (default), the system falls back to standard intrinsic content size behavior.
Practical Examples: Using heightRatio in FrameLayoutKit
Creating a Square Layout (1:1 Aspect Ratio)
To force a view to remain square regardless of its content:
let layout = FrameLayout()
layout.targetView = UIImageView(image: myImage)
layout.heightRatio = 1.0 // height equals width
// isIntrinsicSizeEnabled is automatically set to false
Setting a Custom Aspect Ratio (4:3 or 75%)
For a landscape thumbnail where height should be 75% of the width:
let layout = FrameLayout()
layout.targetView = myContentView
layout.heightRatio = 0.75 // 3:4 ratio (height = 0.75 × width)
layout.allowContentHorizontalGrowing = true
Chainable DSL API Usage
FrameLayoutKit provides a fluent interface via FrameLayout+Chainable.swift:
let layout = FrameLayout()
.heightRatio(1.333) // 4:3 aspect ratio
.allowContentHorizontalGrowing(true)
.target(imageView)
Key Source Files and Implementation Details
The heightRatio functionality is implemented across the following files in the kennic/framelayoutkit repository:
FrameLayoutKit/Classes/FrameLayout.swift– Contains theheightRatioproperty definition (line 46), itsdidSetobserver that disables intrinsic sizing, and thesizeThatFits(_:)override (lines 82–88) that applies the ratio calculation.FrameLayoutKit/Classes/Extensions/FrameLayout+Chainable.swift– Provides theheightRatio(_:)method for DSL-style configuration.FrameLayoutKit/Classes/ScrollStackView.swift– ExposesheightRatioon stack views, demonstrating how the property propagates to child layouts.FrameLayoutKit/Classes/StackFrameLayout.swift– UtilizesheightRatiowhen calculating flexible child layouts within stacks.
Summary
heightRatiois aCGFloatproperty onFrameLayoutthat enforces a fixed aspect ratio by calculating height as a multiple of width.- When set to any value greater than
0, the property automatically disablesisIntrinsicSizeEnabled, preventing the target view’s intrinsic height from affecting layout. - The calculation occurs in
sizeThatFits(_:), where positive ratios override intrinsic sizing and forceheight = width × heightRatio. - Setting
heightRatioto0(the default) restores standard intrinsic content size behavior. - The property is available through both direct assignment and a chainable DSL API.
Frequently Asked Questions
What happens to intrinsic height when heightRatio is set?
When you assign a positive value to heightRatio, the property’s didSet observer automatically sets isIntrinsicSizeEnabled to false. This disables the layout engine’s reliance on the target view’s intrinsicContentSize height, ensuring that height is calculated solely from the width multiplied by the ratio.
Can I use heightRatio with StackFrameLayout?
Yes. StackFrameLayout inherits from FrameLayout and supports heightRatio for its child layouts. When a child within a stack has a positive heightRatio, the stack layout engine respects the calculated height during its measurement pass, making it useful for creating grids or lists with fixed aspect ratio items.
How do I disable heightRatio and return to intrinsic sizing?
Set heightRatio back to 0 (the default value). When the ratio is 0, the sizeThatFits(_:) implementation in FrameLayout.swift skips the ratio-based calculation and falls back to the standard intrinsic content size logic, using contentSizeThatFits(size:) to determine dimensions.
Does heightRatio work with UILabel intrinsic content size?
Yes, but with an important caveat. When you apply a positive heightRatio to a FrameLayout wrapping a UILabel, the layout disables intrinsic sizing and calculates height from the width. This means the label’s text will no longer automatically expand the height to fit its content; instead, the height is constrained by the ratio, potentially truncating text unless you handle it with numberOfLines or auto-shrink settings.
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 →