Skip to content
A grid layout view for SwiftUI
Swift
Branch: master
Clone or download
Latest commit 0745511 Jul 3, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.swiftpm/xcode/package.xcworkspace Initial Commit Jun 26, 2019
Sources/FlowStack Update for Beta 3 Jul 3, 2019
Tests Initial Commit Jun 26, 2019
.gitignore Initial Commit Jun 26, 2019
Package.swift Initial Commit Jun 26, 2019
README.md Add example Jun 26, 2019

README.md

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 can’t perform that action at this time.