How to Use DoubleFrameLayout for Managing Two Views with Flexible Layout Options in FrameLayoutKit

DoubleFrameLayout is a concrete FrameLayout subclass that arranges exactly two child views (or nested layouts) either horizontally or vertically using distribution strategies like equal splits, custom ratios, or intrinsic sizing.

Managing two sibling views with precise layout requirements is straightforward using DoubleFrameLayout from the kennic/framelayoutkit repository. This specialized container provides granular control over axis alignment, space distribution, and overlap behavior through both programmatic APIs and a chainable DSL.

Core Architecture and Frame Structure

DoubleFrameLayout maintains two internal FrameLayout instances—frameLayout1 and frameLayout2—that serve as the actual containers for your target views. According to the source in [DoubleFrameLayout.swift](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/DoubleFrameLayout.swift), these internal frames are added as subviews during initialization and automatically synchronized when configuration properties like ignoreHiddenView, debug, or allowContentSizing change.

The layout algorithm operates in three distinct phases:

  1. Measurement – The sizeThatFits(_:ignoreHiddenView:) method calculates content sizes for each child based on the current axis, distribution, spacing, and edgeInsets.
  2. Composition – The system determines how much space each pane receives according to the NKLayoutDistribution strategy.
  3. Placement – The layoutSubviews() method applies computed frames to frameLayout1 and frameLayout2, accounting for translationOffset or overlapping configurations.

Layout Distribution Strategies

The NKLayoutDistribution enum in DoubleFrameLayout.swift defines five distinct strategies for partitioning space between the two panes:

  • top/left – The first view (top in vertical, left in horizontal) occupies its intrinsic size, while the second view fills the remaining space.
  • bottom/right – The reverse of above; the second view gets intrinsic sizing priority.
  • equal – Both views split the available space 50/50, automatically adjusting if one pane is empty.
  • split(ratio:) – Accepts a custom ratio array (e.g., [0.3, 0.7]) for precise percentage-based allocation.
  • center – Both views are centered within the container with optional spacing between them, collapsing empty panes to zero width.

Practical Implementation Examples

Basic Horizontal Layout with Intrinsic Sizing

This example places two labels side-by-side, giving the left label its intrinsic width while the right label occupies the remaining space:

let leftView = UILabel()
leftView.text = "Left"
let rightView = UILabel()
rightView.text = "Right"

let layout = DoubleFrameLayout { $0
    .axis(.horizontal)
    .distribution(.left)
    .spacing(8)
    .setLeft(leftView)
    .setRight(rightView)
}

The .left distribution ensures frameLayout1 sizes to fit leftView exactly, while frameLayout2 stretches to fill the remaining width minus the 8-point spacing.

Equal-Split Vertical Layout with Overlap

For layered effects where both views share the same geometric bounds:

let top = UIView()
top.backgroundColor = .red
let bottom = UIView()
bottom.backgroundColor = .blue

let layout = DoubleFrameLayout(axis: .vertical, distribution: .equal, views: [top, bottom])
layout.isOverlapped = true
layout.spacing = 0

Setting isOverlapped = true causes both panes to occupy identical frames, useful for creating combined gesture targets or visual blending effects.

Custom Ratio Distribution with Chainable DSL

The companion file DoubleFrameLayout+Chainable.swift provides fluent operators <+ and +> for concise view assignment:

let left = UIView()
let right = UIView()

let layout = DoubleFrameLayout()
    <+ left
    +> right
    .axis(.horizontal)
    .distribution(.split(ratio: [0.3, 0.7]))
    .spacing(12)

Here, <+ assigns left to frameLayout1 and +> assigns right to frameLayout2, distributing 30% of the width to the left pane and 70% to the right.

Centered Single-View Layout

When only one view is present, DoubleFrameLayout automatically collapses the empty pane:

let onlyView = UIButton()
onlyView.setTitle("Only", for: .normal)

let layout = DoubleFrameLayout { $0
    .axis(.horizontal)
    .distribution(.center)
    .spacing(0)
    .setLeft(onlyView)
}

The empty right pane collapses to zero width, centering the button within the container bounds.

Advanced Configuration Options

Beyond basic distribution, DoubleFrameLayout inherits robust capabilities from [FrameLayout.swift](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/FrameLayout.swift):

  • translationOffset – Applies a positional offset to both child frames after layout calculation.
  • shouldCacheSize – Enables size caching for performance optimization in scroll views.
  • skeletonColor/isSkeletonMode – Activates placeholder loading states without additional view hierarchy changes.
  • debug/debugColor – Visualizes layout boundaries for debugging complex interface structures.

Because the class reuses the base FrameLayout logic, it automatically handles intrinsic size propagation, hidden view management via ignoreHiddenView, and edge inset application across both panes.

Summary

  • DoubleFrameLayout manages exactly two views through internal frameLayout1 and frameLayout2 containers defined in DoubleFrameLayout.swift.
  • The NKLayoutDistribution enum provides five strategies: intrinsic priority (left/top or right/bottom), equal splits, custom ratios, and centered alignment.
  • isOverlapped enables layered layouts where both panes share identical bounds.
  • The chainable DSL in DoubleFrameLayout+Chainable.swift offers <+ and +> operators for declarative view assignment.
  • All layout calculations occur in sizeThatFits(_:ignoreHiddenView:) and layoutSubviews(), inheriting caching and debug features from the base FrameLayout class.

Frequently Asked Questions

What is the difference between DoubleFrameLayout and StackFrameLayout?

DoubleFrameLayout is optimized specifically for exactly two child views with precise distribution control, while StackFrameLayout handles N views in a stack arrangement. According to the FrameLayoutKit source, DoubleFrameLayout uses dedicated frameLayout1 and frameLayout2 properties with ratio-based splitting, whereas stack layouts manage dynamic arrays of children.

How do I set custom width ratios between two views?

Use the .split(ratio:) distribution with an array of two CGFloat values representing percentages. For example, .distribution(.split(ratio: [0.25, 0.75])) allocates 25% of the available space to the first view and 75% to the second, as implemented in the sizeThatFits method of DoubleFrameLayout.swift.

Can DoubleFrameLayout handle overlapping views?

Yes. Setting the isOverlapped property to true forces both frameLayout1 and frameLayout2 to occupy the same calculated bounds during layoutSubviews(). This is useful for creating overlay effects or shared gesture targets while maintaining separate view hierarchies.

What happens if one of the two views is empty?

The layout algorithm automatically detects empty panes and collapses their ratio to zero. When using .equal or .split distributions, the non-empty view expands to fill the available space. With .center distribution, the single view centers within the container bounds.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →