Logo

0x3d.Site

is designed for aggregating information.
Welcome
check repository here

FixFlex Logo

FixFlex is a simple yet powerful Auto Layout library built on top of the NSLayoutAnchor API, a swifty and type-safe reimagination of Visual Format Language

Features

  • Declarative Auto Layout code that is easy to write, read, and modify
  • Simple API with 2 functions and 4 specifiers, covering 99% of layout use cases
  • Implementation is only 300 lines of code
  • Compatible with any other Auto Layout code
  • Basically generates a bunch of activated NSLayoutConstraint and UILayoutGuide
  • Keeps your view hierarchy flat, no need for exta containers
  • Lightweight alternative to UIStackView
  • Super straightforward mental model
  • Typesafe alternative to VFL
  • Dynamic Type and Right-To-Left friendly
  • Automatically sets translatesAutoresizingMaskIntoConstraints to false
  • Supports iOS 12.0+ / Mac OS X 10.13+ / tvOS 12.0+

Usage

Imagine we want to create a layout like this:

  1. Let's scan the layout horizontally and translate it into FixFlex code:

Most of the views and spacings have a fixed width (Fix), while the title and subtitle widths are flexible, designed to occupy the remaining space (Flex):

parent.fx.hstack(Fix(15),
                 Fix(iconView, 44),
                 Fix(15),
                 Flex([titleLabel, subtitleLabel]),
                 Fix(15),
                 Fix(chevron, 20),
                 Fix(15))
  1. Vertically, we have three distinct groups of views. Starting with the icon:

We do a spacing at the top using Fix. The bottom spacing should be at least 15pt, for the case when the labels' height is less than the icon's height:

parent.fx.vstack(Fix(15),
                 Fix(iconView, 44),
                 Flex(min: 15))
  1. Next, we perform a vertical scan of the title and subtitle:

parent.fx.vstack(Fix(15),
                 Flex(titleLabel),
                 Flex(subtitleLabel),
                 Fix(15))
  1. Finally, we scan the chevron vertically:

To center the chevron, we ensure the top spacing is equal to the bottom spacing using Fill:

parent.fx.vstack(Fill(),
                 Fix(chevron, 30),
                 Fill())

That's it! The best part is how easy it is to modify FixFlex layout code, inserting extra padding or views effortlessly, without the need to rewire constraints.

API

hstack/vstack

FixFlex provides two functions for laying out views horizontally (hstack) and vertically (vstack), accessible through the view.fx.* namespace.

You can specify startAnchor/endAnchor to layout items between arbitrary anchors instead of the view's edges. startOffset/endOffset are used to add spacing or offsets from the startAnchor and endAnchor respectively.

By default, hstack works in natural positioning mode and operates using leadingAnchor/trailingAnchor. This setup ensures that the layout is mirrored for Right-to-Left languages. However, this behavior can be overridden by enabling the useAbsolutePositioning flag. When this flag is set to true, hstack shifts to using leftAnchor/rightAnchor for layout positioning.

func hstack(
        startAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use leadingAnchor or leftAnchor
        startOffset: CGFloat = 0,
        endAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use trailingAnchor or rightAnchor
        endOffset: CGFloat = 0,
        useAbsolutePositioning: Bool = false, // if true, we use leftAnchor/rightAnchor based positioning (force Left-To-Right)
        _ intents: SizingIntent...
    ) -> StackingResult
func vstack(
        startAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use topAnchor
        startOffset: CGFloat = 0,
        endAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use bottomAnchor
        endOffset: CGFloat = 0,
        _ intents: SizingIntent...
    ) -> StackingResult

A SizingIntent is essentially an instruction for calculating the width or height of:

  • a spacer (for which a UILayoutGuide is created behind the scenes)
  • a view
  • an array of views (when they are aligned in parallel)

Concrete instances of SizingIntent can be created using specialized builder functions:

Fix

Used for specifying the exact size of a view/spacer.

func Fix(_ value: CGFloat) -> SizingIntent

func Fix(_ view: _View, _ value: CGFloat) -> SizingIntent

func Fix(_ views: [_View], _ value: CGFloat) -> SizingIntent

Flex

Useful for sizes that change dynamically. Optionally, it is possible to specify min/max constraints and in-place priority settings for hugging and compression resistance.

func Flex(min: CGFloat? = nil, max: CGFloat? = nil) -> SizingIntent

func Flex(_ view: _View, min: CGFloat? = nil, max: CGFloat? = nil, huggingPriority: _LayoutPriority? = nil, compressionResistancePriority: _LayoutPriority? = nil) -> SizingIntent

func Flex(_ views: [_View], min: CGFloat? = nil, max: CGFloat? = nil, huggingPriority: _LayoutPriority? = nil, compressionResistancePriority: _LayoutPriority? = nil) -> SizingIntent

Fill

Fill allows a view/spacer to proportionally occupy the available free space based on its weight. It's particularly useful for achieving equal spacing, centering elements, or for designing symmetrical layouts like tables or grids.

func Fill(weight: CGFloat = 1.0) -> SizingIntent

func Fill(_ view: _View, weight: CGFloat = 1.0) -> SizingIntent

func Fill(_ views: [_View], weight: CGFloat = 1.0) -> SizingIntent

Match

This is used to match the size of a view or spacer to a specified NSLayoutDimension. It is particularly useful for aligning the sizes of different views or spacers, or for making their sizes proportional to each other.

public func Match(dimension: NSLayoutDimension, multiplier: CGFloat? = nil, offset: CGFloat? = nil) -> SizingIntent

public func Match(_ view: _View, dimension: NSLayoutDimension, multiplier: CGFloat? = nil, offset: CGFloat? = nil) -> SizingIntent

public func Match(_ views: [_View], dimension: NSLayoutDimension, multiplier: CGFloat? = nil, offset: CGFloat? = nil) -> SizingIntent

How it works

FixFlex is not a black box and doesn't use any magic. It is simply a declarative and convenient way to create constraints and layout guides. Let's take a look at how FixFlex is translated into standard Auto Layout calls when we want to center vertically two labels:

parent.fx.hstack(Flex([topLabel, bottomLabel]))

parent.fx.vstack(Fill(),
                 Flex(topLabel),
                 Fix(5),
                 Flex(bottomLabel),
                 Fill())

Under the hood, FixFlex creates constraints and layout guides which equivalent to the following:

topLabel.translatesAutoresizingMaskIntoConstraints = false
bottomLabel.translatesAutoresizingMaskIntoConstraints = false

let layoutGuideTop = UILayoutGuide()
let layoutGuideMiddle = UILayoutGuide()
let layoutGuideBottom = UILayoutGuide()

parent.addLayoutGuide(layoutGuideTop)
parent.addLayoutGuide(layoutGuideMiddle)
parent.addLayoutGuide(layoutGuideBottom)

NSLayoutConstraint.activate([
    // hstack
    topLabel.leadingAnchor.constraint(equalTo: parent.leadingAnchor),
    topLabel.trailingAnchor.constraint(equalTo: parent.trailingAnchor),
    bottomLabel.leadingAnchor.constraint(equalTo: parent.leadingAnchor),
    bottomLabel.trailingAnchor.constraint(equalTo: parent.trailingAnchor),
    //vstack
    layoutGuideTop.topAnchor.constraint(equalTo: parent.topAnchor),
    layoutGuideTop.bottomAnchor.constraint(equalTo: topLabel.topAnchor),
    topLabel.bottomAnchor.constraint(equalTo: layoutGuideMiddle.topAnchor),
    layoutGuideMiddle.heightAnchor.constraint(equalToConstant: 5),
    layoutGuideMiddle.bottomAnchor.constraint(equalTo: bottomLabel.topAnchor),
    bottomLabel.bottomAnchor.constraint(equalTo: layoutGuideBottom.topAnchor),
    layoutGuideBottom.bottomAnchor.constraint(equalTo: parent.bottomAnchor),
    layoutGuideTop.heightAnchor.constraint(equalTo: layoutGuideBottom.heightAnchor),
])

Huh, that's a lot of code to write, and imagine needing to modify it — inserting an extra view or changing the order. Once you try FixFlex, you won't want to go back!

Examples

Fill Parent With Inset

parent.fx.hstack(Fix(15),
                 Flex(child),
                 Fix(15))

parent.fx.vstack(Fix(15),
                 Flex(child),
                 Fix(15))

Pin To Parent Trailing Bottom

parent.fx.hstack(Flex(),
                 Fix(child, 100),
                 Fix(15))

parent.fx.vstack(Flex(),
                 Fix(child, 50),
                 Fix(15))

Center In Parent

parent.fx.hstack(Fill(),
                 Fix(child, 100),
                 Fill())

parent.fx.vstack(Fill(),
                 Fix(child, 50),
                 Fill())

Center Label In Parent

parent.fx.hstack(Fill(),
                 Flex(label),
                 Fill())

parent.fx.vstack(Fill(),
                 Flex(label),
                 Fill())

Vertically Center Two Labels

parent.fx.hstack(Flex([topLabel, bottomLabel]))

parent.fx.vstack(Fill(),
                 Flex(topLabel),
                 Fix(5),
                 Flex(bottomLabel),
                 Fill())

Cell With Icon Title Subtitle And Chevron

parent.fx.hstack(Fix(15),
                 Fix(iconView, 44),
                 Fix(15),
                 Flex([titleLabel, subtitleLabel]),
                 Fix(15),
                 Fix(chevron, 20),
                 Fix(15))

parent.fx.vstack(Fix(15),
                 Fix(iconView, 44),
                 Flex(min: 15))

parent.fx.vstack(Fix(15),
                 Flex(titleLabel),
                 Flex(subtitleLabel),
                 Fix(15))

parent.fx.vstack(Fill(),
                 Fix(chevron, 30),
                 Fill())

Card With Icon Title And Subtitle

parent.fx.hstack(Fix(5),
                 Flex([iconView, titleLabel, subtitleLabel]),
                 Fix(5))

parent.fx.vstack(Fix(5),
                 Fix(iconView, 50),
                 Fix(10),
                 Flex(titleLabel),
                 Flex(subtitleLabel),
                 Fix(5))

Labels Row With Not Enough Space For Both

parent.fx.vstack(Flex([leftLabel, rightLabel]))

parent.fx.hstack(Flex(leftLabel, compressionResistancePriority: .required),
                 Fix(5),
                 Flex(rightLabel))

Labels Split

parent.fx.vstack(Fix(5),
                 Flex([label1, label2, label3]),
                 Fix(5))

parent.fx.hstack(Fix(5),
                 Fill(label1, weight: 2),
                 Fix(5),
                 Fill(label2),
                 Fix(5),
                 Fill(label3),
                 Fix(5))

Flex Min Max

parent.fx.vstack(Fix(5),
                 Flex(label1),
                 Flex(label2),
                 Flex(label3),
                 Fix(5))

parent.fx.hstack(Fix(5),
                 Flex(label1),
                 Flex(),
                 Fix(5))

parent.fx.hstack(Fix(5),
                 Flex(label2, min: 175),
                 Flex(),
                 Fix(5))

parent.fx.hstack(Fix(5),
                 Flex(label3, max: 100),
                 Flex(),
                 Fix(5))

Put Between Anchors

parent.fx.vstack(Flex([label, leadingView, trailingView]))

parent.fx.hstack(Fill(),
                 Flex(label),
                 Fill())

parent.fx.hstack(startAnchor: label.leadingAnchor,
                 endAnchor: label.trailingAnchor,
                 Fix(leadingView, 20),
                 Flex(),
                 Fix(trailingView, 20))

Put Between Anchors Absolute

parent.fx.vstack(Flex([label, leadingView, trailingView]))

parent.fx.hstack(Fill(),
                 Flex(label),
                 Fill())

parent.fx.hstack(startAnchor: label.leftAnchor,
                 endAnchor: label.rightAnchor,
                 useAbsolutePositioning: true,
                 Fix(leadingView, 20),
                 Flex(),
                 Fix(trailingView, 20))

Shadow Using Match

parent.fx.vstack(Fill(),
                 Flex(label),
                 Fill())

parent.fx.hstack(Fill(),
                 Flex(label),
                 Fill())

parent.fx.vstack(startAnchor: label.topAnchor,
                 Fix(10),
                 Match(matchView, dimension: label.heightAnchor),
                 Flex())

parent.fx.hstack(startAnchor: label.leadingAnchor,
                 Fix(10),
                 Match(matchView, dimension: label.widthAnchor),
                 Flex())

Integration

Swift Package Manager

Use Swift Package Manager and add dependency to Package.swift file.

  dependencies: [
    .package(url: "https://github.com/psharanda/FixFlex.git", .upToNextMajor(from: "1.0.0"))
  ]

Alternatively, in Xcode select File > Add Package Dependencies… and add FixFlex repository URL:

https://github.com/psharanda/FixFlex.git

Carthage

Add github "psharanda/FixFlex" to your Cartfile

CocoaPods

FixFlex is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "FixFlex"

Contributing

We welcome contributions! If you find a bug, have a feature request, or want to contribute code, please open an issue or submit a pull request.

License

FixFlex is available under the MIT license. See the LICENSE file for more info.

Swift
Swift
Swift is Apple’s programming language for developing iOS, macOS, and watchOS applications. It’s fast, safe, and easy to learn, with features like type safety and memory management, enabling efficient app development.
GitHub - hirohisa/PageController: Infinite paging controller, scrolling through contents and title bar scrolls with a delay
GitHub - hirohisa/PageController: Infinite paging controller, scrolling through contents and title bar scrolls with a delay
GitHub - Quick/Nimble: A Matcher Framework for Swift and Objective-C
GitHub - Quick/Nimble: A Matcher Framework for Swift and Objective-C
GitHub - roberthein/BouncyLayout: Make. It. Bounce.
GitHub - roberthein/BouncyLayout: Make. It. Bounce.
GitHub - fjcaetano/RxWebSocket: Reactive WebSockets
GitHub - fjcaetano/RxWebSocket: Reactive WebSockets
GitHub - Kitura/Kitura: A Swift web framework and HTTP server.
GitHub - Kitura/Kitura: A Swift web framework and HTTP server.
GitHub - exyte/ProgressIndicatorView: An iOS progress indicator view library written in SwiftUI
GitHub - exyte/ProgressIndicatorView: An iOS progress indicator view library written in SwiftUI
GitHub - rolandleth/LTHRadioButton: A radio button with a pretty animation
GitHub - rolandleth/LTHRadioButton: A radio button with a pretty animation
GitHub - ashishkakkad8/AKSwiftSlideMenu: Slide Menu (Drawer) in Swift
GitHub - ashishkakkad8/AKSwiftSlideMenu: Slide Menu (Drawer) in Swift
GitHub - BastiaanJansen/toast-swift: Customizable Swift Toast view built with UIKit. 🍞
GitHub - BastiaanJansen/toast-swift: Customizable Swift Toast view built with UIKit. 🍞
GitHub - Jintin/Swimat: An Xcode formatter plug-in to format your swift code.
GitHub - Jintin/Swimat: An Xcode formatter plug-in to format your swift code.
GitHub - thoughtbot/Runes: Infix operators for monadic functions in Swift
GitHub - thoughtbot/Runes: Infix operators for monadic functions in Swift
GitHub - tid-kijyun/Kanna: Kanna(鉋) is an XML/HTML parser for Swift.
GitHub - tid-kijyun/Kanna: Kanna(鉋) is an XML/HTML parser for Swift.
GitHub - ParkGwangBeom/Windless: Windless makes it easy to implement invisible layout loading view.
GitHub - ParkGwangBeom/Windless: Windless makes it easy to implement invisible layout loading view.
GitHub - pkluz/PKHUD: A Swift based reimplementation of the Apple HUD (Volume, Ringer, Rotation,…) for iOS 8.
GitHub - pkluz/PKHUD: A Swift based reimplementation of the Apple HUD (Volume, Ringer, Rotation,…) for iOS 8.
GitHub - shtnkgm/ImageTransition: Library for smooth animation of images during transitions.
GitHub - shtnkgm/ImageTransition: Library for smooth animation of images during transitions.
GitHub - hyperoslo/Sugar: :coffee: Something sweet that goes great with your Cocoa
GitHub - hyperoslo/Sugar: :coffee: Something sweet that goes great with your Cocoa
GitHub - mukeshthawani/TriLabelView: A triangle shaped corner label view for iOS written in Swift.
GitHub - mukeshthawani/TriLabelView: A triangle shaped corner label view for iOS written in Swift.
GitHub - yonat/BatteryView: Simple battery shaped UIView
GitHub - yonat/BatteryView: Simple battery shaped UIView
GitHub - suzuki-0000/CountdownLabel: Simple countdown UILabel with morphing animation, and some useful function.
GitHub - suzuki-0000/CountdownLabel: Simple countdown UILabel with morphing animation, and some useful function.
GitHub - sindresorhus/DockProgress: Show progress in your app's Dock icon
GitHub - sindresorhus/DockProgress: Show progress in your app's Dock icon
GitHub - Yalantis/GuillotineMenu: Our Guillotine Menu Transitioning Animation implemented in Swift reminds a bit of a notorious killing machine.
GitHub - Yalantis/GuillotineMenu: Our Guillotine Menu Transitioning Animation implemented in Swift reminds a bit of a notorious killing machine.
GitHub - MrSkwiggs/Netswift: A type-safe, high-level networking solution for Swift apps
GitHub - MrSkwiggs/Netswift: A type-safe, high-level networking solution for Swift apps
GitHub - evermeer/AttributedTextView: Easiest way to create an attributed UITextView (with support for multiple links and from html)
GitHub - evermeer/AttributedTextView: Easiest way to create an attributed UITextView (with support for multiple links and from html)
GitHub - rosberry/texstyle: Format iOS attributed strings easily
GitHub - rosberry/texstyle: Format iOS attributed strings easily
GitHub - ra1028/DiffableDataSources: 💾 A library for backporting UITableView/UICollectionViewDiffableDataSource.
GitHub - ra1028/DiffableDataSources: 💾 A library for backporting UITableView/UICollectionViewDiffableDataSource.
GitHub - Mijick/PopupView: Popups presentation made simple (SwiftUI)
GitHub - Mijick/PopupView: Popups presentation made simple (SwiftUI)
GitHub - envoy/Embassy: Super lightweight async HTTP server library in pure Swift runs in iOS / MacOS / Linux
GitHub - envoy/Embassy: Super lightweight async HTTP server library in pure Swift runs in iOS / MacOS / Linux
GitHub - shima11/FlexiblePageControl: A flexible UIPageControl like Instagram.
GitHub - shima11/FlexiblePageControl: A flexible UIPageControl like Instagram.
GitHub - ChiliLabs/CHIOTPField: CHIOTPField is a set of textfields that can be used for One-time passwords, SMS codes, PIN codes, etc. Mady by @ChiliLabs - https://chililabs.io
GitHub - ChiliLabs/CHIOTPField: CHIOTPField is a set of textfields that can be used for One-time passwords, SMS codes, PIN codes, etc. Mady by @ChiliLabs - https://chililabs.io
GitHub - LeonardoCardoso/SectionedSlider: iOS 11 Control Center Slider
GitHub - LeonardoCardoso/SectionedSlider: iOS 11 Control Center Slider
Swift
More on Swift

Programming Tips & Tricks

Code smarter, not harder—insider tips and tricks for developers.

Error Solutions

Turn frustration into progress—fix errors faster than ever.

Shortcuts

The art of speed—shortcuts to supercharge your workflow.
  1. Collections 😎
  2. Frequently Asked Question's 🤯

Tools

available to use.

Made with ❤️

to provide resources in various ares.