A grid layout view for SwiftUI

Related tags

Layout FlowStack
Overview

Update July 2020 - latest SwiftUI now has built-in components to do this, which should be used instead.

FlowStack

FlowStack is a SwiftUI component for laying out content in a grid.

Requirements

Xcode 11 beta on MacOS 10.14 or 10.15

Installation

In Xcode, choose File -> Swift Packages -> Add Package Dependency and enter this repo's URL.

Usage

FlowStack(columns, numItems, alignment) { index, colWidth in }

columns (Int)
The number of columns to display.
numItems (Int)
The total count of items you will be displaying.
alignment (HorizontalAlignment?)
Default: .leading
The alignment of any trailing columns in the last row.

Callback parameters

index (Int)
The index of the item currently being processed.
colWidth (CGFloat)
The computed width of the column currently being processed.

Examples

1) Simple

The simplest possible example:

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  Text(" \(index) ").frame(width: colWidth)
}

You should always add .frame(width: colWidth) to the immediate child of FlowStack.

Screen Shot 2019-06-25 at 10 43 41 PM

2) Displaying Data

struct Item {
  var image: String
  var label: String
}

let items = [
  Item(image: "hand.thumbsup", label: "Up"),
  Item(image: "tortoise", label: "Tortoise"),
  Item(image: "forward", label: "Forward"),
  Item(image: "hand.thumbsdown", label: "Down"),
  Item(image: "hare", label: "Hare"),
  Item(image: "backward", label: "Backward")
]

FlowStack(columns: 3, numItems: items.count, alignment: .leading) { index, colWidth in
  Button(action: { print("Tap \(index)!") }) {
    Image(systemName: items[index].image)
    Text(items[index].label).font(Font.caption)
  }
  .padding()
  .frame(width: colWidth)
}

Screen Shot 2019-06-25 at 10 54 25 PM

Padding/Borders/Actions

Let's draw a border on our cells to visualize some concepts:

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  Text(" \(index) ").frame(width: colWidth).border(Color.gray)
}

Screen Shot 2019-06-25 at 11 03 05 PM

Now let's swap the .frame and .border order and note what happens. This demonstrates the order of operations is important when chaining layout modifiers.

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  Text(" \(index) ").border(Color.gray).frame(width: colWidth)
}

Screen Shot 2019-06-25 at 11 04 58 PM

Now let's swap the order back and add some padding:

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  Text(" \(index) ").padding().frame(width: colWidth).border(Color.gray)
}

Screen Shot 2019-06-25 at 11 10 10 PM

To add actions, you can of course just put buttons in your cells like example #2. But there is also a way to detect a tap on the entire cell. Note we add a background to detect taps in the empty areas outside the text.

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  Text(" \(index) ")
    .padding()
    .frame(width: colWidth)
    .border(Color.gray)
    .background(Color.white)
    .tapAction {
      print("Tap!")
    }
}

Example with images

Here's an example with images. LoadableImageView is from here.

FlowStack(columns: 3, numItems: 27, alignment: .leading) { index, colWidth in
  VStack {
    LoadableImageView(with: "https://cataas.com/cat?type=sq?foo")
      .padding()
      .frame(width: colWidth, height: colWidth)
      .tapAction { print("Meow!") }
    Text(" \(index) ")
  }
  .padding()
  .frame(width: colWidth)
  .border(Color.gray)
  .background(Color.white)
  .tapAction {
    print("Tap!")
  }
}

Screen Shot 2019-06-25 at 11 41 18 PM

Evenly spaced grid

FlowStack(columns: 4, numItems: 27, alignment: .leading) { index, colWidth in
  LoadableImageView(with: "https://cataas.com/cat?type=sq?rando")
    .padding(5)
    .frame(width: colWidth, height: colWidth)
}.padding(5)

Screen Shot 2019-06-26 at 12 13 21 AM

Feedback

Please file a github issue if you're having trouble or spot a bug.

You might also like...
MyLayout is a simple and easy objective-c framework for iOS view layout
MyLayout is a simple and easy objective-c framework for iOS view layout

MyLayout is a powerful iOS UI framework implemented by Objective-C. It integrates the functions with Android Layout,iOS AutoLayout,SizeClass, HTML CSS float and flexbox and bootstrap. So you can use LinearLayout,RelativeLayout,FrameLayout,TableLayout,FlowLayout,FloatLayout,PathLayout,GridLayout,LayoutSizeClass to build your App 自动布局 UIView UITableView UICollectionView RTL

A Code challenge I solved leveraging a lot on Composite collection view layout written in swift

AsthmApp Mobile app designed as a support aid for people with Asthma Accounts Google and Firebase [email protected] dICerytiMPSI Facebook asthmp.ap

A Code challenge I solved leveraging a lot on Composite collection view layout...written in swift

Space44 Code Challenge Space44 Code Challenge iOS application for Space 44 hiring process, it leverages on Image download and composite collection vie

A flexible collection view with proper horizontal layout flow
A flexible collection view with proper horizontal layout flow

FlexCollection A very simple flexible collection view using SwiftUI that automat

Expose layout margins and readable content width to SwiftUI's Views

SwiftUI Layout Guides This micro-library exposes UIKit's layout margins and readable content guides to SwiftUI. Usage Make a view fit the readable con

SwiftUI views that arrange their children in a flow layout.
SwiftUI views that arrange their children in a flow layout.

SwiftUI Flow SwiftUI views that arrange their children in a flow layout. HFlow A view that arranges its children in a horizontal flow. Usage ScrollVie

SwiftUI views that arrange their children in a Pinterest-like layout
SwiftUI views that arrange their children in a Pinterest-like layout

SwiftUI Masonry SwiftUI views that arrange their children in a Pinterest-like layout. HMasonry A view that arranges its children in a horizontal mason

Reframing SwiftUI Views. A collection of tools to help with layout.
Reframing SwiftUI Views. A collection of tools to help with layout.

Overview A Swift Package with a collection of SwiftUI framing views and tools to help with layout. Size readers like WidthReader, HeightReader, and on

Arrange views in your app’s interface using layout tools that SwiftUI provides.

Composing custom layouts with SwiftUI Arrange views in your app's interface using layout tools that SwiftUI provides. Overview This sample app demonst

Comments
  • Patch 1

    Patch 1

    the former version did not compile on current Xcode versions as of 11.0, I think. The compiler could not determine the view type. by adding some automatically computed variables it is compiling, again.

    opened by GoldenStat 0
  • license

    license

    I notice most swift code is released under no license. Coming from JS, where 98%+ has MIT it's not as easy to get going with! Maybe consider adding a permissive license.

    opened by natew 0
  • The compiler is unable to type-check this expression in reasonable time

    The compiler is unable to type-check this expression in reasonable time

    It seems that beta5 broke the code: .../SourcePackages/checkouts/FlowStack/Sources/FlowStack/FlowStack.swift:35:5: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

    opened by farcaller 15
Owner
John Susek
John Susek
Simple Catalyst example (Mac idiom) of a grid-based app populated with photos, with dynamic cell layout switching

Catalyst Photo Grid Simple Catalyst example (Mac idiom) of a grid-based app populated with photos that can animate its cells between two different lay

Steven Troughton-Smith 56 Nov 14, 2022
The most powerful Grid container missed in SwiftUI

Grid Grid view inspired by CSS Grid and written with SwiftUI We are a development agency building phenomenal apps. Overview Grid is a powerful and eas

Exyte 1.2k Jan 2, 2023
A custom layout built on top of SwiftUI's Layout API that lays elements out in multiple lines. Similar to flex-wrap in CSS, CollectionViewFlowLayout.

WrapLayout A custom layout built on top of SwiftUI's Layout API that lays elements out in multiple lines. Similar to flex-wrap in CSS, CollectionViewF

Hiroshi Kimura 6 Sep 27, 2022
Auto Layout (and manual layout) in one line.

Auto Layout (and manual layout) in one line. Quick Look view.bb.centerX().below(view2).size(100) It’s equivalent to iOS 9 API: view.centerXAnchor.cons

Javier Zhang 74 Oct 19, 2022
Auto Layout made easy with the Custom Layout.

Auto Layout made easy with the Custom Layout. Getting started CocoaPods CocoaPods is a dependency manager for Cocoa projects. You can install it with

Malith Nadeeshan 1 Jan 16, 2022
AppStoreClone - Understanding the complex layout of app store using UICompositional layout in swift

AppStoreClone Understanding the complex layout of app store using UICompositiona

Dheeraj Kumar Sharma 8 Dec 28, 2022
Flow layout / tag cloud / collection view in SwiftUI.

SwiftUIFlowLayout A Flow Layout is a container that orders its views sequentially, breaking into a new "line" according to the available width of the

Gordan Glavaš 115 Dec 28, 2022
LayoutKit is a fast view layout library for iOS, macOS, and tvOS.

?? UNMAINTAINED ?? This project is no longer used by LinkedIn and is currently unmaintained. LayoutKit is a fast view layout library for iOS, macOS, a

LinkedIn's Attic 3.2k Dec 27, 2022
Programmatic view layout for the rest of us.

Façade Important Facade is no longer under active development, and as such if you create any issues or submit pull requests, it's not very likely to b

Mike 696 Aug 3, 2022
LayoutKit is a fast view layout library for iOS, macOS, and tvOS.

?? UNMAINTAINED ?? This project is no longer used by LinkedIn and is currently unmaintained. LayoutKit is a fast view layout library for iOS, macOS, a

LinkedIn's Attic 3.2k Jan 4, 2023