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

> Learn to manage two views with DoubleFrameLayout in FrameLayoutKit. Explore flexible layout options for equal splits, custom ratios, or intrinsic sizing to enhance your UI.

- Repository: [Nam Kennic/framelayoutkit](https://github.com/kennic/framelayoutkit)
- Tags: how-to-guide
- Published: 2026-03-05

---

**`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/main/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`](https://github.com/kennic/framelayoutkit/blob/main/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:

```swift
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:

```swift
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`](https://github.com/kennic/framelayoutkit/blob/master/FrameLayoutKit/Classes/Extensions/DoubleFrameLayout+Chainable.swift) provides fluent operators `<+` and `+>` for concise view assignment:

```swift
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:

```swift
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/main/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`](https://github.com/kennic/framelayoutkit/blob/main/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`](https://github.com/kennic/framelayoutkit/blob/main/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.