SkillAgentSearch skills...

UICollectionViewSplitLayout

UICollectionViewSplitLayout makes collection view more responsive.

Install / Use

/learn @yahoojapan/UICollectionViewSplitLayout
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

uicollectionviewsplitlayout_logo

Platform Swift 4.2 License Version Carthage compatible

UICollectionViewSplitLayout makes collection view more responsive.

oct-30-2018 19-53-04

What's this?

UICollectionViewSplitLayout is a subclass of UICollectionViewLayout. It can divide sections into two columns.

Collection view has "Section" which organizes item collection. UICollectionViewFlowLayout places them from top to bottom.

On the other hands, UICollectionViewSplitLayout divides sections into two columns. You can dynamically update the width of them and which column each section is on.

For example, UICollectionViewSplitLayout can change the number of column according to device orientation. All you need is assigning value to leftSideRatio when changing screen size. This figure describes that a collection view has three sections (red, blue and green) and UICollectionViewSplitLayout aligns them side by side.

rendering_well

UICollectionViewSplitLayout looks like UIStackView. But it has a more memory efficient architecture. So you can align a lot of cells with it.

It may be hard to imagine how it works, please run EmojiCollectionViewController.

Requirement

  • iOS 9.0+
  • Swift 4.2

Installation

Carthage

1. create Cartfile

github "https://github.com/yahoojapan/UICollectionViewSplitLayout"

2. install

> carthage update

CocoaPods

1. create Podfile

platform :ios, '8.0'
use_frameworks!

pod "UICollectionViewSplitLayout", :git => 'https://github.com/yahoojapan/UICollectionViewSplitLayout.git'

2. install

> pod install

Getting Started

It’s good to start from replacing UICollectionViewFlowLayout with UICollectionViewSplitLayout.

1. Create UICollectionViewController

Set UICollectionViewController on Storyboard.

<img width="300" alt="2018-10-24 10 28 36" src="https://user-images.githubusercontent.com/18320004/47400738-7e9c7e80-d779-11e8-9753-52e62ced2afc.png">

Add implementation to construct a collection view.

import UIKit

private let reuseIdentifier = "Cell"

class BasicCollectionViewController: UICollectionViewController {
    
    var dataSource: [[UIColor]] = [
        (0..<20).map { _ in .red },
        (0..<20).map {  _ in .blue },
        (0..<20).map {  _ in .green }
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }
    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return dataSource.count
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource[section].count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        cell.backgroundColor = dataSource[indexPath.section][indexPath.row]
        return cell
    }
}

Build the code.

<img width="300" alt="2018-10-24 10 27 42" src="https://user-images.githubusercontent.com/18320004/47400781-b4d9fe00-d779-11e8-86e7-2d35ab45822c.png">

It shows three sections whose items have different colors.

2. Input "UICollectionViewSplitLayout" as Custom Layout Class

Switch "Flow" to "Custom" in Layout attribute and input "UICollectionViewSplitLayout" into Class and Module attributes.

<img width="316" alt="2018-10-30 11 07 59" src="https://user-images.githubusercontent.com/18320004/47691120-1e538400-dc34-11e8-821b-3b9bafb2dbfc.png">

3. Assign parameters to UICollectionViewSplitLayout object

Connect the layout class to source code. Assign the parameters on viewDidLoad()

    @IBOutlet weak var layout: UICollectionViewSplitLayout!
 
    override func viewDidLoad() {
        super.viewDidLoad()
        //...
        //...
        
        // margins for each section
        layout.minimumItemLineSpacing = 8
        layout.minimumInterItemSpacing = 8
        layout.sectionInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
        
        // Column Setting
        layout.leftSideRatio = 0.4
        layout.splitSpacing = 8
       
        //...
        //...
    }

4. Implement the layout delegate for UICollectionViewSplitLayout

Implement UICollectionViewDelegateTwoColumnLayout. The following methods is required.

extension BasicCollectionViewController: UICollectionViewDelegateSectionSplitLayout {
    // Fix the size of each item as UICollectionViewDelegateFlowLayout does. calculateFixedWidthRaughly() is utility method UICollectionViewSplitLayout has.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath, width: CGFloat, side: UICollectionViewSplitLayoutSide) -> CGSize {
        let width = layout.calculateFixedWidthRaughly(
                               to: 3, 
                               of: side, 
                               minimumInterItemSpacing: layout.minimumInterItemSpacing, 
                               sectionInset: layout.sectionInset)
        return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sideForSection section: Int) -> UICollectionViewSplitLayoutSide {
        // when a section number is odd, the items are placed into left side. 
        return section % 2 == 0 ? .left : .right
    }
}

It arranges the sections side by side.

<img width="300" alt="2018-10-30 23 41 03" src="https://user-images.githubusercontent.com/18320004/47726194-52af5a80-dc9d-11e8-82da-72e799837f6c.png">

See BasicCollectionViewController to run the above example.

Architecture

It is one of the UICollectionViewLayout. So you can change a layout without updating code in UICollectionViewDelegate and UICollectionViewDataSource. It is reasonable to apply a new layout. All you have to do is studying layout class and the delegate.

Usage

How to Split

UICollectionViewSplitLayout calculates width of the left and right side with the following parameter.

leftSideRatio = 0.4

It has a Float value which is the ration of left side to the entire width. In addition, left and right sides have spacing between them.

splitSpacing = 10

If a collection view has 110pt width, the above setting requires 40pt width to the left side and 60pt width to the right side. When leftSideRatio has 0.0, splitSpacing is ignored as an exception.

You can choose which side each section is in. UICollectionViewDeleagteSectionSplitLayout provides a method to do that.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sideForSection section: Int) -> UICollectionViewSplitLayoutSide

UICollectionViewSplitLayout hooks the delegate every time a collection view calls invalidateLayout().

Margins

UICollectionViewSplitLayout has these parameters to determine margins.

/// The minimum spacing to use between items in the same row.
open var minimumInterItemSpacing: CGFloat
/// The minimum spacing to use between lines of items in the grid.
open var minimumItemLineSpacing: CGFloat
/// The margins used to lay out content in a section
open var sectionInset: UIEdgeInsets

They have the corresponding delegate methods by section (optional).

// section inset to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> UIEdgeInsets
    
// minimumInterItemSpacing to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInterItemSpacingForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> CGFloat

// minimumItemLineSpacing to each section
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumItemLineSpacingForSectionAtIndex section: Int, side: UICollectionViewSplitLayoutSide) -> CGFloat

Pinning (iOS 11~)

UICollectionViewSplitLayout pins seciton header like UICollectionViewFlowLayout. This feature is supported from iOS 11. sectionPinToVisibleBounds enables to work it.

Setting Attriutes

UICollectionViewSplitLayout uses three kinds of attribute, item, supplementary view

Related Skills

View on GitHub
GitHub Stars239
CategoryDevelopment
Updated4d ago
Forks12

Languages

Swift

Security Score

100/100

Audited on Mar 26, 2026

No findings