Blueprints is a collection of flow layouts that is meant to make your life easier when working with collection view flow layouts.

Overview

Blueprints logo Blueprints Preview

CI Status Version Carthage Compatible Code Coverage License Platform Swift

Description

Blueprints Icon

Blueprints is a collection of flow layouts that is meant to make your life easier when working with collection view flow layouts. It comes with two built-in layouts that are highly flexible and easy to configure at the call-site. They support properties like items per row and items per column; this will calculate the layout attributes needed for fitting the number of views that you want to appear on the screen.

The framework also provides a good base for your custom implementations. By extending the core blueprint layout, you get built-in support for animations and layout attribute caching. The bundled default animator supports animations that look very similar to what you get from a vanilla table view. If you want to provide your collection view animator, no problem; you can inject an animator of your choosing when initializing the layout.

Features

  • 🍭 Animation support
  • 🀳🏻 Optimized for performance
  • πŸ“ Built-in vertical and horizontal layouts
  • πŸ“° Supports header and footers
  • πŸ– Supports sticky headers and footers
  • 🌈 Built-in mosiac layout
  • πŸ’¦ Built-in vertical layout that supports waterfall
  • πŸ“± iOS support
  • πŸ’» macOS support
  • πŸ“Ί tvOS support
  • πŸ¦– Objective-C support

Supporting the project

If you want to support the development of this framework, you can do so by becoming a sponsor. ❀️

Preview

iOS macOS
iOS PReview macOS Preview

How do items per row work?

If you specify how many items per row that you want to appear in a vertical layout, the width of the layout attribute will be calculated for you taking the section inset, item spacing into account to make sure that all views fit your design. For example, if you set that you want two items per row, then two views will appear on the same row side by side. If you want to create a table view layout, you would simply set the items per row value to be one. You can use this variable for horizontal layouts as well, but instead of creating a new row, the value is used to create a width to cover the desired area. If you want the width to span across the entire container then simply set it to one, if you want to create a carousel layout with hinting, setting a value like 1.1 will render at least one complete item and give a visual hint to the user that another view is available if the scroll horizontally.

How do items per column work?

Items per column are explicitly for horizontal layouts and are used to decide how many items that should be shown on screen but using a vertical axis. If you set it to two, it will display two views, one above and one below and then continue to build the rest of the views horizontally, following the same pattern.

How does item sizes work?

It works just like a regular flow layout, but with a twist. If you want to provide a static size using the regular item size, you are free to do so. As mentioned above, you can also provide the number of views that you want visible on the screen based on the container views width. To provide dynamic sizing, you can make your collection view delegate conform to UICollectionViewDelegateFlowLayout or NSCollectionViewDelegateFlowLayout. That way you can compute the values based on the data coming from the data source etc. Worth noting is that using itemsPerRow takes precedence over the other alternatives.

Dynamic sizing preview

Usage

Vertical layout

let blueprintLayout = VerticalBlueprintLayout(
  itemsPerRow: 1.0,
  height: 50,
  minimumInteritemSpacing: 10,
  minimumLineSpacing: 10,
  sectionInset: EdgeInsets(top: 10, left: 10, bottom: 10, right: 10),
  stickyHeaders: true,
  stickyFooters: false
)
let collectionView = UICollectionView(frame: .zero,
                                      collectionViewLayout: blueprintLayout)

Horizontal layout

let blueprintLayout = HorizontalBlueprintLayout(
  itemsPerRow: 1.0,
  itemsPerColumn: 2,
  height: 50,
  minimumInteritemSpacing: 10,
  minimumLineSpacing: 10,
  sectionInset: EdgeInsets(top: 10, left: 10, bottom: 10, right: 10),
  stickyHeaders: true,
  stickyFooters: true
)
let collectionView = UICollectionView(frame: .zero,
                                      collectionViewLayout: blueprintLayout)

Mosaic layout

let mosaicLayout = VerticalMosaicBlueprintLayout(
  patternHeight: 400,
  minimumInteritemSpacing: 2,
  minimumLineSpacing: 2,
  sectionInset: EdgeInsets(top: 2, left: 2, bottom: 2, right: 2),
  patterns: [
    MosaicPattern(alignment: .left, direction: .vertical, amount: 2, multiplier: 0.6),
    MosaicPattern(alignment: .left, direction: .horizontal, amount: 2, multiplier: 0.33),
    MosaicPattern(alignment: .left, direction: .vertical, amount: 1, multiplier: 0.5),
    MosaicPattern(alignment: .left, direction: .vertical, amount: 1, multiplier: 0.5)
  ])
let collectionView = UICollectionView(frame: .zero,
                                      collectionViewLayout: mosaicLayout)

Installation

Blueprints is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Blueprints'

Blueprints is also available through Carthage. To install just write into your Cartfile:

github "zenangst/Blueprints"

Blueprints can also be installed manually. Just download and drop Sources folders in your project.

Author(s)

Contributing

We would love you to contribute to Blueprints, check the CONTRIBUTING file for more info.

License

Blueprints is available under the MIT license. See the LICENSE file for more info.

Comments
  • Multiple Sections?

    Multiple Sections?

    Is there a way to use this with multiple sections? When I set the layout, it crashes and I get this error:

    Thread 1: Fatal error: Index out of range
    

    It traces back to the VerticalBlueprintLayout.swift's class prepare() method:

            if section == layoutAttributes.count {
              layoutAttributes.append([layoutAttribute])
            } else {
              layoutAttributes[section].append(layoutAttribute)
            }
    

    The objective was to make the 2nd and 3rd sections of the collection view use the VerticalBlueprintLayout while keeping the 1st section customized.

    bug 
    opened by HackShitUp 12
  • Mosaic Layout

    Mosaic Layout

    I'm having troubles understanding how the Mosaic Layout works...

    I don't understand why the first "block" isn't aligned on the right.

    simulator screen shot - iphone 8 - 2018-09-13 at 18 51 27

    let mosaicLayout = VerticalMosaicBlueprintLayout(
      itemSize: CGSize.init(width: 50, height: 400),
      minimumInteritemSpacing: 15,
      minimumLineSpacing: 15,
      sectionInset: EdgeInsets(top: 15, left: 15, bottom: 15, right: 15),
      patterns: [
        MosaicPattern(alignment: .left, direction: .vertical, amount: 2, multiplier: 0.5),
        MosaicPattern(alignment: .left, direction: .horizontal, amount: 2, multiplier: 0.33),
        MosaicPattern(alignment: .left, direction: .vertical, amount: 1, multiplier: 0.5),
        MosaicPattern(alignment: .right, direction: .vertical, amount: 2, multiplier: 0.5)
    ])
    
    bug 
    opened by guidev 12
  • Unable to scroll past all items in the collection view. Affects both horizontal and vertical layout when using dynamic heights.

    Unable to scroll past all items in the collection view. Affects both horizontal and vertical layout when using dynamic heights.

    I know changes haven't been made to the horizontal layout to fully support dynamic heights however I thought it worth mentioning here that both are affected in slightly different ways.

    Vertical: If the previous columns last item has a greater height than the last item in the last column, then the scrollview bounds are pinning against the last item. This stops the user from scrolling which in turn cuts off the collection view cell.

    screenshot 2018-12-13 at 13 16 50

    Horizontal:

    When scrolling around the cells disappear and re-appear, this is only an issue if items per rows is been used alongside items per column. However this may not be the intended use for a Horizontal layout and will probably be addressed in #43

    bug 
    opened by christoff-1992 9
  • #47 fix incorrect previous x offset been used

    #47 fix incorrect previous x offset been used

    Fixes #47

    Required or the wrong item is looked-up from the layoutAttributes when using headers.

    @zenangst - Have left the variable for sectionMaxY for the time been as I believe this will be required to resolve the issue with the incorrect position of the footer when multiple columns are used.

    opened by christoff-1992 8
  • Changing the dataSource can cause the cachedItems layoutAttributes to become nil, when the updated datasource has items for section at index.

    Changing the dataSource can cause the cachedItems layoutAttributes to become nil, when the updated datasource has items for section at index.

    I have observed the following behaviour when updating the dataSource and updating the collectionViewLayout. (As different cells are been used and they have a different height between the datasources)

    1. CollectionView with segmented control that changes the datasource.
    2. The first datasource has items, the second datasource has no items, the third datasource has items.
    3. When switching to the empty datasource the cached items will become nil as there are no items in the section.
    4. When switching to a datasource with items after this, the cached items correctly updates initially but then somewhere along the chain it invalidates the cached items returning them to the nil state. I am not sure what is causing this at the moment as the blueprint layout correctly sets this and super is always called before the cached items have been set.
    5. When layoutAttibutesForItem(at indexPath: IndexPath) is called, as the cached items have been invalidated, an index out of bounds exception is caused.

    implementing a safe check for the index resolves the issues, however I am not sure what's causing the cached items to become nil in the first place.

    override open func layoutAttributesForItem(at indexPath: IndexPath) -> LayoutAttributes? {
        let compare: (LayoutAttributes) -> Bool
        #if os(macOS)
          compare = { indexPath > $0.indexPath! }
        #else
          compare = { indexPath > $0.indexPath }
        #endif
    
        guard cachedItems[safe:indexPath.section] != nil else {
            return nil
        }
    
        let result = binarySearch.findElement(in: cachedItems[indexPath.section],
                                              less: compare,
                                              match: { indexPath == $0.indexPath })
        return result
      }
    
    subscript (safe index: Int) -> Element? {
            return index < count ? self[index] : nil
        }
    

    I will add an example asap and will continue to hunt down what may be causing the cached items to become nil.

    bug 
    opened by christoff-1992 8
  • Recommended approach to dynamic height using UICollectionViewDelegateFlowLayout

    Recommended approach to dynamic height using UICollectionViewDelegateFlowLayout

    Hey just wondering what the recommended approach is to using items per row with dynamic height, do we have to load a dummy cell to calculate the height and return this in the sizeForItemAt?

    Likewise to support self sizing headers, at the moment the headerReferenceSize is been used to set the height. As a result the delegate method for referenceSizeForHeaderInSection is not called. Is this a limitation of the layout?

    bug question 
    opened by christoff-1992 7
  • Horizontal Layout - layout attributes for supplementary items changed without invalidating the layout.

    Horizontal Layout - layout attributes for supplementary items changed without invalidating the layout.

    If headers and footers are been used the horizontal layout will crash when been set.

    2018-12-14 11:33:41.254874+0000 Example-iOS[2682:570726] *** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore/UIKit-3698.93.8/UICollectionViewData.m:459
    2018-12-14 11:33:41.256220+0000 Example-iOS[2682:570726] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path (<NSIndexPath: 0x281b59b00> {length = 2, path = 0 - 0}) changed from <UICollectionViewLayoutAttributes: 0x104700dd0> index path: (<NSIndexPath: 0x281b582e0> {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 61);  to <UICollectionViewLayoutAttributes: 0x104704650> index path: (<NSIndexPath: 0x281b59b00> {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 1835 61);  without invalidating the layout'
    *** First throw call stack:
    (0x1c05fbea0 0x1bf7cda40 0x1c0511c1c 0x1c0fff140 0x1ecfbb2ac 0x1ecfba814 0x1ecfbce30 0x1ecf8f594 0x1ecf8eaa8 0x1ecf8e668 0x102f03db0 0x102ee9c80 0x1edb528b4 0x1edb52ed0 0x102f03b68 0x102f0d0f4 0x102f0d044 0x102f0d154 0x1ed6ba768 0x1ece8a6ec 0x1ece8a61c 0x1ed6ba768 0x1ed1486d0 0x1ed1489f0 0x1ed1479f0 0x1ed6f418c 0x1ed6f53f0 0x1ed6d46ec 0x1ed7a057c 0x1ed7a2f74 0x1ed79ba64 0x1c058c1cc 0x1c058c14c 0x1c058ba30 0x1c05868fc 0x1c05861cc 0x1c27fd584 0x1ed6b9054 0x102ed8288 0x1c0046bb4)
    libc++abi.dylib: terminating with uncaught exception of type NSException
    
    bug 
    opened by christoff-1992 6
  • Implement delegate methods for header/footer reference size

    Implement delegate methods for header/footer reference size

    This implements the delegate methods for header/footer reference sizes so they can be provided just like we do for the items.

    This will allow users to provide dynamic heights for headers and footers if they wish.

    enhancement 
    opened by christoff-1992 5
  • OSX example doesn't compile

    OSX example doesn't compile

    Compile OSX framework is Ok Compile OSX example is ok but problem is link the message error are:

    Undefined symbols for architecture x86_64: "___llvm_profile_runtime", referenced from: ___llvm_profile_runtime_user in BlueprintLayoutAnimator.o ___llvm_profile_runtime_user in BlueprintLayoutAnimation.o ___llvm_profile_runtime_user in TypeAlias.o ___llvm_profile_runtime_user in BlueprintLayoutAnimationType.o (maybe you meant: ___llvm_profile_runtime_user) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

    compiled with XCode 10.2.1

    opened by DevulderJeanPaul 5
  • Bug/rogue calls to prepare without invalidating the context

    Bug/rogue calls to prepare without invalidating the context

    Fixes #107 - I don't think we should be having to do this, but occasionally prepare is called without the context been invalidated causing additional calls to things like sizeForItemAt.

    This would normally go unnoticed, but I have been playing around with resizable child containers that have collection views with the custom layouts.

    Occasionally the rogue calls would add more items than needed into the dynamic height cache I had held causing some cells to have the incorrect size.

    opened by christoff-1992 5
  • Improve mosaic blueprint initializer

    Improve mosaic blueprint initializer

    This PR changes the initializer of the Mosaic layout to only include a pattern height instead of an item size. The width of the item is never used so this change is motivated by removing the confusion that it might be used. The new label is called patternHeight.

    Reference: https://github.com/zenangst/Blueprints/issues/43

    enhancement 
    opened by zenangst 5
  • [SUGGESTION] AutoCenter flow

    [SUGGESTION] AutoCenter flow

    Hello πŸ‘‹ , first of all thanks for this project!

    I'd like to know if it would be possible to auto-compute the sectionInset based on the layout (and with self cell size calculation) πŸ˜„ .

    Regards

    opened by RSickenberg 3
  • Update default number of sections

    Update default number of sections

    This should be 0 not 1 as we can't assume a value. It can cause issues if the collection view is using headers and footers, as the collection view attempts to dequeue a header/footer that has yet to be registered. fixes #139

    Blocked - Requires further changes 
    opened by christoff-1992 1
  • Number of sections should default to 0

    Number of sections should default to 0

    The number of sections should default to 0 to stop subsequent calls been made to other delegate methods when there are no items to be displayed.

    https://github.com/zenangst/Blueprints/blob/c3dc5442d3102d933bc439c5c845b277b20034b1/Sources/Shared/Core/BlueprintLayout.swift#L38

    This would cause a crash if headers/footers where been dequeued.

    opened by christoff-1992 1
  • Dynamic heights for headers and footers breaks cell positioning.

    Dynamic heights for headers and footers breaks cell positioning.

    When using dynamic heights for headers and footers the height of the collection view is incorrect. The last item will be overlapped by the footer due to the footers dynamic size not been taken into account. This had been fine in the past and may be related to some of the refactoring between #131 and master.

    bug 
    opened by christoff-1992 0
Releases(0.13.1)
Owner
Christoffer Winterkvist
random hero at @finkoslo by day, cocoa vigilante by night, dad at dawn. my life is awesome. Previously @hyperoslo
Christoffer Winterkvist
πŸ”„ GravitySlider is a beautiful alternative to the standard UICollectionView flow layout.

GravitySliderFlowLayout Made by Applikey Solutions Find this project on Dribbble Table of Contents Purpose Supported OS & SDK Versions Installation Us

Applikey Solutions 958 Dec 23, 2022
Lightweight custom collection view inspired by Airbnb.

ASCollectionView Lightweight custom collection view inspired by Airbnb. Screenshots Requirements ASCollectionView Version Minimum iOS Target Swift Ver

Abdullah Selek 364 Nov 24, 2022
An easy-to-use Collection View Layout for card-like animation.

CarLensCollectionViewLayout An easy-to-use Collection View Layout for card-like animation ?? CarLensCollectionViewLayout was created out of the implem

Netguru 530 Dec 16, 2022
UICollectionViewSplitLayout makes collection view more responsive.

UICollectionViewSplitLayout makes collection view more responsive. What's this? UICollectionViewSplitLayout is a subclass of UICollectionViewLayout. I

Yahoo! JAPAN 239 Dec 6, 2022
Declaretive UICollectionViewCompositionalLayout interface to implement complex collection view layout.

CompositionalLayoutViewController Example To run the example project, clone the repo, and run pod install from the Example directory first. Requiremen

ONEinc 19 Dec 2, 2022
Easy way to integrate pagination with dummy views in CollectionView, make Instagram "Discover" within minutes.

AZCollectionView Controller Features Automatic pagination handling No more awkward empty CollectionView screen AZ CollectionVIew controller give you a

Afroz Zaheer 95 May 11, 2022
CardsLayout is a lightweight Collection Layout.

CardsLayout is a lightweight Collection Layout. Installation CocoaPods

Filipp Fediakov 798 Dec 28, 2022
This component allows for the transfer of data items between collection views through drag and drop

Drag and Drop Collection Views Written for Swift 4.0, it is an implementation of Dragging and Dropping data across multiple UICollectionViews. Try it

Michael Michailidis 508 Dec 19, 2022
Gliding Collection is a smooth, flowing, customizable decision for a UICollectionView Swift Controller.

A smooth, flowing, customizable decision for a UICollectionView Swift Controller We specialize in the designing and coding of custo

Ramotion 1.5k Dec 19, 2022
Easy and type-safe iOS table and collection views in Swift.

Quick Start TL;DR? SimpleSource is a library that lets you populate and update table views and collection views with ease. It gives you fully typed cl

Squarespace 96 Dec 26, 2022
A mirror of Apple's sample code for high performance collection views in iOS 15.

Building High-Performance Lists and Collection Views Improve the performance of lists and collections in your app with prefetching and image preparati

Tim Oliver 14 Nov 12, 2022
FSPagerView is an elegant Screen Slide Library. It is extremely helpful for making Banner View、Product Show、Welcome/Guide Pages、Screen/ViewController Sliders.

SWIFT OBJECTIVE-C FSPagerView is an elegant Screen Slide Library implemented primarily with UICollectionView. It is extremely helpful for making Banne

Wenchao Ding 6.7k Jan 2, 2023
iOS custom view to display books on shelf

ShelfView (iOS) iOS custom view to display books on shelf (Android version is available here) Requirements iOS 10.0+ Swift 4.2 Installation ShelfView

Adeyinka Adediji 268 Dec 10, 2022
Useful SwiftUI container view's. FittingGeometry, ScrollableView, LayoutReader, PageView, UIKitView. (iOS)

Containers Also available as a part of my SwiftUI+ Collection – just add it to Xcode 13+ Useful SwiftUI container view's for additional convenience. I

SwiftUI+ 32 Dec 27, 2022
Blueprints - A framework that is meant to make your life easier when working with collection view flow layouts.

Description Blueprints is a collection of flow layouts that is meant to make your life easier when working with collection view flow layouts. It comes

Christoffer Winterkvist 982 Dec 7, 2022
A beautiful set of predefined colors and a set of color methods to make your iOS/OSX development life easier.

Installation Drag the included Colours.h and Colours.m files into your project. They are located in the top-level directory. You can see a demo of how

Ben Gordon 3.1k Dec 28, 2022
This app is a sample app that recognizes specific voice commands such as "make it red", "make it blue", "make it green", and "make it black" and change the background color of the view in the frame.

VoiceOperationSample This app is a sample app that recognizes specific voice commands such as "make it red", "make it blue", "make it green", and "mak

Takuya Aso 3 Dec 3, 2021
GraphQLite is a toolkit to work with GraphQL servers easily. It also provides several other features to make life easier during iOS application development.

What is this? GraphQLite is a toolkit to work with GraphQL servers easily. It also provides several other features to make life easier during iOS appl

Related Code 2.8k Jan 9, 2023
SwiftUI implementation of Conway’s Game of Life β€” also known as β€œLife”.

Life Conway’s Game of Life SwiftUI implementation of Conway’s Game of Life β€” also known simply as β€œLife”. About I’m Martin, an indie dev from Berlin.

Martin Lexow 23 Jan 21, 2022
This package is meant to make http request of an easy way inspiren in the architecture of Moya package

NetworkAgent This package is meant to make http request of an easy way inspiren in the architecture of Moya package. This package is 100% free of depe

Angel Rada 19 Sep 8, 2022