Exyte Grid

repository·master·Indexed 24 days ago

https://github.com/exyte/grid

A high-performance SwiftUI layout engine providing a flexible grid system. It supports complex layouts including spanning, custom track sizing (fixed, fit, and fractional), and advanced auto-placement strategies like dense packing. Features include GridGroup for exceeding view limits, configurable flow directions, content modes, and support for animations via the .gridAnimation() modifier.

Tokens
1.9K
Snippets
8
Records
16
Agent score
35%

What's inside exyte-grid

  1. Configure Grid Content Mode

    master

    The content mode determines how the grid behaves when its content exceeds the available space or when tracks are non-flexible.

    • .fill (Default): The grid attempts to fill the entire space provided by the parent. Tracks orthogonal to the flow direction are implicitly treated as .fr(1).
    • .scroll: The grid content becomes scrollable in the growing direction. Tracks orthogonal to the flow direction are implicitly treated as .fit.
    Grid(tracks: 3) {
        // ... content
    }
    .gridContentMode(.scroll)
  2. Configure Grid Packing mode

    master

    Packing defines the strategy used by the auto-placement algorithm to handle holes left by spanning items.

    • .sparse (Default): The algorithm only moves "forward". It never backtracks to fill holes, ensuring items appear in their intended order.
    • .dense: The algorithm attempts to fill holes earlier in the grid if smaller items are encountered later. This may cause items to appear out of order.
    Grid(tracks: 4) {
        // ... content
    }
    .gridPacking(.dense)
  3. Use GridGroup to exceed view limits

    master

    The number of views directly inside a Grid's ViewBuilder closure is limited to 10. To include more views, use GridGroup.

    Unlike a standard SwiftUI Group, GridGroup treats every view inside it as a separate grid item. It also supports being initialized with a Range, Identifiable models, or an explicit ID. You can use GridGroup.empty to represent the absence of content.

    Note: To ensure smooth animations, it is recommended to use GridGroup with Identifiable models or explicit IDs so that view identities are preserved during transitions.

  4. Configure Grid Flow direction

    master

    Grid flow defines the direction in which items grow. You can specify this in the Grid constructor or via the .gridFlow(...) modifier.

    • .rows (Default): The number of columns is fixed (defined by track sizes). Items move across columns and switch to a new row when the last column is reached. The number of rows grows.
    • .columns: The number of rows is fixed. Items move down rows and switch to a new column when the last row is reached. The number of columns grows.
  5. Install Grid by building from sources

    master

    If you want to build the project from source, follow these steps:

    1. Clone the repository:
      git clone git@github.com:exyte/Grid.git
    2. Navigate to the Example directory:
     ```shell
    cd Grid/Example/
    1. Install dependencies:
      pod install
    4. Open the workspace:
     ```shell
    open Example.xcworkspace/
    git clone git@github.com:exyte/Grid.git
    cd Grid/Example/
    pod install
    open Example.xcworkspace/
  6. Initialize a Grid

    master

    You can instantiate a Grid in several ways depending on your data source:

    1. Static Views: Provide only the track count and a ViewBuilder closure.
    2. Range: Provide a Range<Int> to iterate over indices.
    3. Identifiable Entities: Provide a collection of Identifiable models.
    4. Explicit ID: Provide a collection and a KeyPath to specify the identifier.
  7. Install Grid via Swift Package Manager

    master

    To add Grid as a dependency using Swift Package Manager (SPM):

    1. In Xcode, go to the File menu.
    2. Select Swift Packages › Add Package Dependency…
    3. Enter https://github.com/exyte/Grid in the package repository URL field.
    4. Follow the Xcode prompts to complete the installation.
  8. Set explicit view start positions

    master

    Use the .gridStart(column:row:) modifier to place a view at a specific coordinate.

    Placement Priority:

    1. Views with both column and row specified are placed first.
    2. Views with either column or row specified are placed next (auto-placement algorithm handles conflicts).
    3. Views with no explicit start position are placed last.
    ColorView(.red)
        .gridStart(row: 1)
        .gridSpan(column: 2, row: 2)
    
    ColorView(.purple)
        .gridStart(column: 3, row: 0)
  9. Span grid views across rows or columns

    master

    Use the .gridSpan(column:row:) modifier to allow a view to occupy multiple tracks. The default span is 1.

    Note: A view with a span $\ge 2$ that covers flexible tracks does not participate in the fractional space distribution for those tracks; it simply fits the spanned area.

    Grid(tracks: [.fr(1), .pt(150), .fr(2)]) {
        ColorView(.blue)
            .gridSpan(column: 2)
        ColorView(.purple)
            .gridSpan(row: 2)
        ColorView(.red)
    }
  10. Use @GridBuilder for conditional logic

    master

    The Grid and GridGroup builders support standard Swift control flow statements like if/else, if let, and switch.

    You can also use the @GridBuilder attribute on functions or variables to return heterogeneous views or complex conditional logic while maintaining compatibility with the grid's layout engine.

    @GridBuilder
    func headerSegment(flag: Bool) -> some View {
        if flag {
            GridGroup { /* ... */ }
        } else {
            ColorView(.black)
        }
    }
  11. Animate Grid content updates

    master

    You can define a specific animation for grid transitions using the .gridAnimation() modifier.

    To ensure smooth and correct animations (especially when items move or change identity), use ForEach or GridGroup initialized with Identifiable models or explicit IDs. This allows SwiftUI to track the identity of views as they move between grid positions.

    Grid(models, id: \.self, tracks: 3) {
        VCardView(text: $0.text, color: $0.color)
    }
    .gridAnimation(.default)