programming
mobile development
UI design
iOS development
Swift

How to create fixed space and flexible space bar button items programmatically?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In UIKit, fixed-space and flexible-space UIBarButtonItem objects are mainly used in toolbars to control horizontal spacing between real buttons. A fixed space reserves an exact width, while a flexible space expands to consume any extra room left in the toolbar.

Fixed Space vs Flexible Space

These two system items solve different layout problems:

  • 'fixedSpace creates a known gap, measured in points'
  • 'flexibleSpace grows or shrinks as the toolbar width changes'

That distinction matters because a fixed space is about precision, while a flexible space is about distribution. If the layout needs to adapt across iPhone sizes and rotations, flexible spacing is usually the better default.

Create a Fixed Space Item

A fixed space item becomes useful only after you assign its width.

swift
1import UIKit
2
3let fixedSpace = UIBarButtonItem(
4    barButtonSystemItem: .fixedSpace,
5    target: nil,
6    action: nil
7)
8fixedSpace.width = 24

Without a width, the item exists but does not communicate any meaningful spacing intent.

Create a Flexible Space Item

A flexible space item does not need a width because UIKit calculates it automatically.

swift
1import UIKit
2
3let flexibleSpace = UIBarButtonItem(
4    barButtonSystemItem: .flexibleSpace,
5    target: nil,
6    action: nil
7)

You usually place this between real buttons so the available room gets pushed into the gap.

Build a Toolbar Item Array

The most common place to use these items is a UIToolbar.

swift
1import UIKit
2
3let saveButton = UIBarButtonItem(
4    barButtonSystemItem: .save,
5    target: self,
6    action: #selector(saveTapped)
7)
8
9let deleteButton = UIBarButtonItem(
10    barButtonSystemItem: .trash,
11    target: self,
12    action: #selector(deleteTapped)
13)
14
15let fixedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
16fixedSpace.width = 16
17
18let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
19
20toolbar.setItems([saveButton, flexibleSpace, deleteButton, fixedSpace], animated: false)

In that layout, the flexible space pushes the save and delete buttons apart, while the fixed space preserves a small constant gap at the end.

Full Programmatic Example

Here is a minimal view controller that creates a toolbar entirely in code:

swift
1import UIKit
2
3final class EditorViewController: UIViewController {
4    private let toolbar = UIToolbar()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.backgroundColor = .systemBackground
9
10        toolbar.translatesAutoresizingMaskIntoConstraints = false
11        view.addSubview(toolbar)
12
13        NSLayoutConstraint.activate([
14            toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
15            toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
16            toolbar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
17        ])
18
19        let saveButton = UIBarButtonItem(
20            barButtonSystemItem: .save,
21            target: self,
22            action: #selector(saveTapped)
23        )
24
25        let composeButton = UIBarButtonItem(
26            barButtonSystemItem: .compose,
27            target: self,
28            action: #selector(composeTapped)
29        )
30
31        let flexible = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
32        let fixed = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
33        fixed.width = 12
34
35        toolbar.setItems([saveButton, flexible, composeButton, fixed], animated: false)
36    }
37
38    @objc private func saveTapped() {
39        print("save")
40    }
41
42    @objc private func composeTapped() {
43        print("compose")
44    }
45}

This is the programmatic equivalent of configuring toolbar spacing in Interface Builder.

Toolbars and Navigation Bars Are Not the Same

A common source of confusion is trying to use these spacing items in a navigation bar the same way they behave in a toolbar. Their behavior is most predictable in UIToolbar item arrays. Navigation bars often need custom views, layout margins, or appearance configuration instead of toolbar-style spacing items.

So the answer depends not only on the API call, but also on where the item will be used.

Common Pitfalls

Creating a fixed-space item without assigning its width leaves you with no intentional spacing, even though the code appears complete.

Expecting flexible space to create a specific pixel gap is incorrect because it expands dynamically to consume remaining toolbar width.

Using too many fixed spaces can make a toolbar look brittle across device sizes because the layout stops adapting naturally.

Trying to apply toolbar spacing assumptions directly to navigation bars often produces confusing results because the two layout systems behave differently.

Adding spacing items when a custom view or stack-based layout would be clearer can overcomplicate the interface.

Summary

  • Create fixed-space and flexible-space items with UIBarButtonItem system items.
  • Set width on a fixed-space item to control an exact gap.
  • Use flexible space when the layout should adapt to available width.
  • These items are most predictable inside UIToolbar configurations.
  • Choose fixed or flexible spacing based on whether the design needs precision or adaptability.

Course illustration
Course illustration

All Rights Reserved.