Skip to content

A SwiftUI library for creating masonry grid layouts with items of varying heights

Notifications You must be signed in to change notification settings

imben123/Masonry

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Masonry

A SwiftUI library for creating masonry grid layouts with items of varying heights.

Platform Swift

Masonry layout example

Features

  • Pure SwiftUI - Based on a SwiftUI Grid
  • Masonry layout - Items of varying heights flow naturally
  • Responsive columns - Column count adjusts based on available width
  • Lazy rendering - Only visible cells are rendered for optimal performance
  • Focus state support - Full integration with SwiftUI's focus system

Installation

Swift Package Manager

Add Masonry to your Package.swift:

dependencies: [
    .package(url: "https://github.com/imbn123/Masonry.git", branch: "main")
]

Quick Start

import Masonry
import SwiftUI

// 1. Define your item type conforming to MasonryItem
struct PhotoItem: MasonryItem {
    let id: UUID
    let imageURL: URL
    let aspectRatio: CGFloat

    var preferredHeight: MasonryItemHeight {
        switch aspectRatio {
        case ..<0.7: return .extraLarge
        case 0.7..<0.9: return .large
        case 0.9..<1.1: return .medium
        case 1.1..<1.4: return .small
        default: return .extraSmall
        }
    }
}

// 2. Create your view
struct PhotoGrid: View {
    let photos: [PhotoItem]

    var body: some View {
        ScrollView {
            MasonryView(items: photos, spacing: 8) { photo, focusBinding in
                AsyncImage(url: photo.imageURL) { image in
                    image.resizable().scaledToFill()
                } placeholder: {
                    Color.gray
                }
                .clipShape(RoundedRectangle(cornerRadius: 8))
            }
        }
    }
}

API Reference

MasonryView

The main view component for creating masonry layouts.

MasonryView(
    items: [Item],
    minItemWidth: CGFloat? = nil,
    width: CGFloat? = nil,
    spacing: CGFloat = 8,
    itemView: (Item, FocusState<Item.ID?>.Binding) -> ItemView
)

MasonryItem Protocol

All items displayed in a MasonryView must conform to this protocol.

public protocol MasonryItem: Hashable, Identifiable, Sendable {
    @MainActor var preferredHeight: MasonryItemHeight { get }
}

MasonryItemHeight

An enum representing five height levels for masonry items.

Case Height Multiplier Visual Height
.extraSmall 0.5x 50% of cell height
.small 0.75x 75% of cell height
.medium 1.0x 100% (one full cell)
.large 1.25x 125% of cell height
.extraLarge 1.5x 150% of cell height

Properties

// Get the height multiplier for calculations
let multiplier = MasonryItemHeight.large.heightMultiplier // 1.25

// Iterate all cases
for height in MasonryItemHeight.allCases {
    print(height.debugDescription)
}

Usage Examples

Basic Grid

struct BasicGrid: View {
    @State private var items: [MyItem] = []

    var body: some View {
        ScrollView {
            MasonryView(items: items) { item, _ in
                RoundedRectangle(cornerRadius: 8)
                    .fill(item.color)
            }
            .padding()
        }
    }
}

With Focus State

MasonryView(items: items) { item, focusBinding in
    ItemView(item: item)
        .focused(focusBinding, equals: item.id)
}

Keyboard Navigation

On iOS 17+ and macOS 14+, Masonry supports keyboard navigation:

  • Move to the previous item
  • Move to the next item
  • Move to the item above
  • Move to the item below

Focus state is automatically managed through the FocusState<Item.ID?>.Binding provided in the item view closure.

Environment Values

requestHeightUpdate

Request a layout recalculation when item content changes dynamically.

struct DynamicItem: View {
    @Environment(\.requestHeightUpdate) private var requestHeightUpdate
    @State private var isExpanded = false

    var body: some View {
        VStack {
            Text("Content")
            if isExpanded {
                Text("More content...")
            }
        }
        .onTapGesture {
            isExpanded.toggle()
            requestHeightUpdate()
        }
    }
}

Requirements

  • iOS 16.0+ / macOS 14.0+
  • Swift 6.2+
  • Xcode 16.0+

License

See the LICENSE file for details.

About

A SwiftUI library for creating masonry grid layouts with items of varying heights

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages