SpanGrid is an enriched SwiftUI LazyVGrid that supports a number of extra features.

Overview

SpanGrid

SpanGrid is an enriched SwiftUI LazyVGrid that supports a number of extra features.

A basic example output of a SpanGrid with four cells reading the sentence: Welcome to SpanGrid! The latest in SwiftUI grid goodness.

Features

Column Span

All items in the data source must conform to SpanGridSizeInfoProvider. This protocol adds a single parameter to your data which informs the grid as to how many columns it should fill.

Options include:

  • A single cell which is the same width as a column.
  • A full row which will cover all columns, no matter how many columns there are.
  • A custom span which allows you to specify the exact number of columns. If the value provided is larger than the number of columns, then it will fill the row.

If a cell cannot fit in the remaining space of a row, then it will create a new row leaving whitespace on the previous one.

Row Size Strategy

When returning your custom view for each cell, it will arrive with a metadata model. This model will include information such as the calculated height of the row. This value may also be nil in scenarios where we have yet to calculate it.

Options include:

  • A fixed size where all rows will be the same height that you have provided.
  • square where the height of each row is the same as the width of a single column. If your row contains a span of >1, it will still only return the width of a single column.
  • largest will return the height of the largest cell in the row allowing for all cells to be of equal height.
  • none (default) will never return a height.

Column Size Strategy

The width of a single column, the number of columns and the space between columns can be calculated in a number of ways.

Options include:

  • A fixed provider which allows you to strictly specify the three values above.
  • dynamic (default) provides an opinionated column structure which adapts to the size of the device and includes some accessibility changes.
  • custom allows you to provide your own implementation. This will provide you with the current width of the grid.

Notes

I do not pledge to be an expert in SwiftUI, so there may be many issues with the current implementation. I have tested it the best I can and have seen no real issues with performance or functionality. Feel free to raise issues or pull requests with enhancements, bug fixes, ideas, etc.

No Jordan, this project is not called Spandex, no matter how many times you say it.

Comments
  • macOS Support

    macOS Support

    This project is currently only working for iOS/iPadOS, given it exclusively uses SwiftUI there should be no technical limitation caused by expanding support to macOS, and potentially even tvOS.

    opened by Sherlouk 2
  • Improve Project Compatibility

    Improve Project Compatibility

    Closes #3

    • Improved Catalyst Support
    • Fixed tvOS Support
    • Added macOS Support
    • Added watchOS Support

    TODO

    • [x] Break SpanGrid down into a few entities
      • Move the three rowHeightLookup items into own extension
      • Move maths calculations into own file
    • [ ] Remove requirement for horizontalSizeClass
    • [ ] Improve highlight/focus state across supported platforms
      • Use arrow keys on supported platforms
      • Ensure consistent API across platforms
      • Ensure strong compatibility with accessibility tools (try navigate with games console, Switch Control, etc)
      • Add keyboard navigation to macOS (currently disabled, unsure why)
    • [x] Move SpanGridWidthListener into own group
      • See if we can reduce duplication (publisher/notification)
    • [ ] Add test suite covering all supported platforms
      • Use XCTSkipUnless to detect platform early on.
    • [ ] Add missing app icons?

    Separate Ticket

    • [x] Add CI to run tests on all supported platforms, using GitHub Actions
    • [ ] Improve sample app to showcase a few different options
      • A navigation tab will demonstrate a complex layout that is easily navigate-able using non-touch inputs
      • Sidebar on macOS, tab view on iOS, tvOS, and Catalyst, unsure on watchOS.
      • Could also try doing a SwiftUI widget too? Same reusable content.
    • [ ] Improve Documentation
      • DocC tutorial?
      • Inline documentation
    • [ ] Refine SpanGridDynamicColumnSizeStrategy further 👀
    • [x] Add SwiftLog and remove all the print statements we have
    opened by Sherlouk 1
  • Row height lookup incorrect for cells with whitespace prefix

    Row height lookup incorrect for cells with whitespace prefix

    Imagine a grid with 3 columns with the layout below:

    [ X X O ] (2 items followed by whitespace) [ XXXX ] (single item filling entire row)

    We are currently assigning the rowOffset of row 0 (first row) to the item with the full width tile. This is because we calculate the maths based on the first item in the technical grid, even if it's not rendered that way. We need to update the maths to take into account prefix cells.

    bug 
    opened by Sherlouk 1
  • Add Keyboard Navigation

    Add Keyboard Navigation

    Started testing this with a local project and it works fairly well. The biggest issue currently is that it really struggles around whitespace so we need to handle cell prefix in the maths calculations.

    There also appears to be a fairly big performance penalty when dealing with large data sets in monkey mode. The numbers don't scare me since this is a manual user input which itself has time to register, but it would be nice to investigate some basic optimisations around that.

    Finally, I'm trying to wrap my head around how keyboard navigation would work for cells with nested content. I'm thinking about the App Store layout where a cell can itself be another horizontal scrolling grid (a carousel).

    How should keyboard navigation work with this? How can we add support for it? Could we make our solution more generic so it could be accessed by the public interface? We need to setup an example demonstrating this.

    Arrow key navigation was not working on simulator, unsure why. Need to try on a physical device to see if there's a SwiftUI limitation there. Also, if we can't disable discoverability then we need to allow developers to pass through localised strings.

    Video demonstrating behaviour: https://user-images.githubusercontent.com/15193942/135714274-6af1a55b-14e2-4ce3-b386-2f76302360d4.mov

    TODO

    • [x] 🚨 ~~Should use arrow keys instead of WASD~~ Not possible due to Apple limitation
    • [x] Should disable discoverability, or allow user to localise
    • [x] Fix issue with navigation around whitespace (cell prefix)
    • [x] Fix performance with constantly looping over full cell cache
    • [x] ⚠️ ~~Allow user to have cells opt out of keyboard navigation (would skip, similar to whitespace)~~ Out of scope for MVP
    • [x] Hide the keyboard input buttons
    • [x] Update documentation
    opened by Sherlouk 0
  • Asynchronous Cells

    Asynchronous Cells

    Some cells will not immediately have data available to them, for example adverts, and will require a mechanism that allows to asynchronously load data. This is currently possible with SpanGrid.

    What would be nice though is to add a demonstration of how you can dynamically insert or remove items into the grid efficiently based on network requests.

    It may also be worth exploring the ability for SpanGrid to manage some level of async cell where, on failure, it would remove the tile.

    More to think about here.

    opened by Sherlouk 0
  • Keyboard Navigation

    Keyboard Navigation

    We should add the ability to navigate the grid using your attached keyboard, useful for both iPadOS and macOS (support pending).

    It should support the four cardinal directions, respect whitespace and span size. It should be completely opt-in.

    Implementation started in #1.

    opened by Sherlouk 2
Releases(0.0.4)
  • 0.0.4(Oct 10, 2021)

  • 0.0.3(Oct 2, 2021)

    ⚠️ Contains breaking changes.

    Renamed dynamic column provider Allow some custom configuration to dynamic column provider Pass UITraitCollection to complete custom column provider Add tvOS 14 support Add Mac Catalyst support Add keyboard navigation support

    Source code(tar.gz)
    Source code(zip)
  • 0.0.2(Sep 30, 2021)

Owner
James Sherlock
James Sherlock
🎛 QGrid: The missing SwiftUI collection view.

[NOTE] If you'd like to see QGrid in action, check out this demo of QDesigner (see video below). Install QDesigner: https://apps.apple.com/us/app/qdes

Q Mobile 1.5k Dec 23, 2022
A flexible grid layout view for SwiftUI

?? GridStack A flexible grid layout view for SwiftUI. WWDC20 Update Apple  released LazyVGrid and LazyHGrid at WWDC20. If you are fine to only suppor

Peter Minarik 620 Nov 11, 2022
APDynamicGrid is a SwiftUI package that helps you create consistent and animatable grids.

APDynamicGrid Overview APDynamicGrid is a SwiftUI package that helps you create consistent and animatable grids. The DynamicGrid View preserves the sa

Antonio Pantaleo 29 Jul 4, 2022
This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

Fun 60 Dec 17, 2022
TextFieldFormatter - Simple Text Formatter (Credit Card Number, Phone Number, Serial Number etc.)

TextFieldFormatter Simple Text Formatter (Credit Card Number, Phone Number, Seri

Anıl ORUÇ 4 Apr 4, 2022
A simple designable subclass on UILabel with extra IBDesignable and Blinking features.

JSLabel Demo pod try JSLabel ...or clone this repo and build and run/test the JSLabel project in Xcode to see JSLabel in action. If you don't have Coc

Jogendra 6 May 9, 2022
Simple class to check if app has been cracked, being debugged or enriched with custom dylib

iOS-App-Security-Class Simple class to check if iOS app has been cracked, being debugged or enriched with custom dylib and as well detect jailbroken e

Unhandled Exception 74 Mar 11, 2022
Exemplify a LazyVGrid in SwiftUI in a MVVM pattern with Mock Data and images in assets.

SwiftUI-LazyVGrid Exemplify a LazyVGrid in SwiftUI in a MVVM pattern with Mock Data and images in assets. Screenshots Samples IP & Credits All those b

Ethan Halprin 3 Aug 9, 2022
PixabayImageSearchSample - SwiftUI + LazyVGrid + Pixabay API + Codable + sync/async Sample

PixabayImageSearchSample SwiftUI + LazyVGrid + Pixabay API + Codable + sync/asyn

null 3 Nov 23, 2022
NumberMorphView a view like label for displaying numbers which animate with transition using a technique called number tweening or number morphing.

NumberMorphView a view like label for displaying numbers which animate with transition using a technique called number tweening or num

Abhinav Chauhan 1.6k Dec 21, 2022
SecureDefaults is a wrapper over UserDefaults/NSUserDefaults with an extra AES-256 encryption layer

SecureDefaults for iOS, macOS Requirements • Usage • Installation • Contributing • Acknowledgments • Contributing • Author • License SecureDefaults is

Victor Peschenkov 216 Dec 22, 2022
A lightweight generic cache for iOS written in Swift with extra love for images.

Haneke is a lightweight generic cache for iOS and tvOS written in Swift 4. It's designed to be super-simple to use. Here's how you would initalize a J

Haneke 5.2k Dec 11, 2022
Light wrapper of UIButton that allows extra customization for tvOS

FocusTvButton Light wrapper of UIButton that allows extra customization for tvOS If you would like to have the same level of customization in tablevie

David Cordero 68 Nov 12, 2022
Light wrapper of UITableViewCell that allows extra customization for tvOS

TvOSCustomizableTableViewCell Light wrapper of UITableViewCell that allows extra customization for tvOS If you would like to have the same level of cu

Zattoo 31 Nov 9, 2022
It is a highly configurable iOS library which allows easy styling with built in styles as well as extra header and footer views so that you can make extremely unique alerts and action sheets.

 CFAlertViewController CFAlertViewController is a library that helps you display and customise Alerts, Action Sheets, and Notifications on iPad and i

Crowdfire Inc. 1.1k Dec 18, 2022
A lightweight generic cache for iOS written in Swift with extra love for images.

Haneke is a lightweight generic cache for iOS and tvOS written in Swift 4. It's designed to be super-simple to use. Here's how you would initalize a J

Haneke 5.2k Dec 29, 2022
CryptoWatch is an application to fetch the currency datas from an api and show their updated values to user. User is able to get the coin datas without an extra effort.

CryptoTracker In order to combine my work and studies, I made a small project that keeps the user's registration datas in memory, checks them when nee

Ömer Faruk Kılıçaslan 2 Jun 27, 2022
A number of preset loading indicators created with SwiftUI

ActivityIndicatorView A number of preset loading indicators created with SwiftUI We are a development agency building phenomenal apps. Usage Create an

Exyte 956 Dec 26, 2022
A number of preset loading indicators created with SwiftUI

ActivityIndicatorView A number of preset loading indicators created with SwiftUI We are a development agency building phenomenal apps. Usage Create an

Exyte 956 Dec 26, 2022
Elegant SwiftUI phone number textField.

iPhoneNumberField ☎️ Format phone numbers as they're typed—entirely in SwiftUI. ?? Get Started | Examples | Customize | Features | Install | And it's

Seyed Mojtaba Hosseini Zeidabadi 358 Dec 30, 2022