Home

Awesome

SquareMosaicLayout

Version License Platform

An extandable mosaic UICollectionViewLayout with a focus on extremely flexible customizations.

Note

This layout is not of waterfall type. It was designed for layouts where we can predict the size of rectangular box which contains the number of full cells. Check out how to copy TRMosaicLayout or FMMosaicLayout using SquareMosaicLayout

Visual

ExampleLayoutPatternBlocks
image1image2image3image4
Build and run an example project to see how it really worksLet's imagine that we want a UICollectionView with some mosaic layout that looks like thisThe red part of frames repeats while scrolling. So we should do only the red pattern and then repeat itThe pattern is split it into smaller blocks that can be reused for some other layout or pattern

Installation

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

pod 'SquareMosaicLayout', '4.1.2'

Capabilities

Author

iwheelbuy, iwheelbuy@gmail.com

License

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

Example - copying TRMosaicLayout

final class TRMosaicLayoutCopy: SquareMosaicLayout, SquareMosaicDataSource {
    
    convenience init() {
        self.init(direction: SquareMosaicDirection.vertical)
        self.dataSource = self
    }

    func layoutPattern(for section: Int) -> SquareMosaicPattern {
        return TRMosaicLayoutCopyPattern()
    }
}

class TRMosaicLayoutCopyPattern: SquareMosaicPattern {
    
    func patternBlocks() -> [SquareMosaicBlock] {
        return [
            TRMosaicLayoutCopyBlock1(),
            TRMosaicLayoutCopyBlock2()
        ]
    }
}

public class TRMosaicLayoutCopyBlock1: SquareMosaicBlock {
    
    public func blockFrames() -> Int {
        return 3
    }
    
    public func blockFrames(origin: CGFloat, side: CGFloat) -> [CGRect] {
        let minWidth = side / 3.0
        let maxWidth = side - minWidth
        let minHeight = minWidth * 1.5
        let maxHeight = minHeight + minHeight
        var frames = [CGRect]()
        frames.append(CGRect(x: 0, y: origin, width: maxWidth, height: maxHeight))
        frames.append(CGRect(x: maxWidth, y: origin, width: minWidth, height: minHeight))
        frames.append(CGRect(x: maxWidth, y: origin + minHeight, width: minWidth, height: minHeight))
        return frames
    }
}

public class TRMosaicLayoutCopyBlock2: SquareMosaicBlock {
    
    public func blockFrames() -> Int {
        return 3
    }
    
    public func blockFrames(origin: CGFloat, side: CGFloat) -> [CGRect] {
        let minWidth = side / 3.0
        let maxWidth = side - minWidth
        let minHeight = minWidth * 1.5
        let maxHeight = minHeight + minHeight
        var frames = [CGRect]()
        frames.append(CGRect(x: 0, y: origin, width: minWidth, height: minHeight))
        frames.append(CGRect(x: 0, y: origin + minHeight, width: minWidth, height: minHeight))
        frames.append(CGRect(x: minWidth, y: origin, width: maxWidth, height: maxHeight))
        return frames
    }
}

Example - copying FMMosaicLayout

final class FMMosaicLayoutCopy: SquareMosaicLayout, SquareMosaicDataSource {
    
    convenience init() {
        self.init(direction: SquareMosaicDirection.vertical)
        self.dataSource = self
    }
    
    func layoutPattern(for section: Int) -> SquareMosaicPattern {
        return FMMosaicLayoutCopyPattern()
    }
}

class FMMosaicLayoutCopyPattern: SquareMosaicPattern {
    
    func patternBlocks() -> [SquareMosaicBlock] {
        return [
            FMMosaicLayoutCopyBlock1(),
            FMMosaicLayoutCopyBlock2(),
            FMMosaicLayoutCopyBlock3(),
            FMMosaicLayoutCopyBlock2(),
            FMMosaicLayoutCopyBlock2()
        ]
    }
}

public class FMMosaicLayoutCopyBlock1: SquareMosaicBlock {
    
    public func blockFrames() -> Int {
        return 5
    }
    
    public func blockFrames(origin: CGFloat, side: CGFloat) -> [CGRect] {
        let min = side / 4.0
        let max = side - min - min
        var frames = [CGRect]()
        frames.append(CGRect(x: 0, y: origin, width: max, height: max))
        frames.append(CGRect(x: max, y: origin, width: min, height: min))
        frames.append(CGRect(x: max, y: origin + min, width: min, height: min))
        frames.append(CGRect(x: max + min, y: origin, width: min, height: min))
        frames.append(CGRect(x: max + min, y: origin + min, width: min, height: min))
        return frames
    }
}

public class FMMosaicLayoutCopyBlock2: SquareMosaicBlock {
    
    public func blockFrames() -> Int {
        return 4
    }
    
    public func blockFrames(origin: CGFloat, side: CGFloat) -> [CGRect] {
        let min = side / 4.0
        var frames = [CGRect]()
        frames.append(CGRect(x: 0, y: origin, width: min, height: min))
        frames.append(CGRect(x: min, y: origin, width: min, height: min))
        frames.append(CGRect(x: min * 2, y: origin, width: min, height: min))
        frames.append(CGRect(x: min * 3, y: origin, width: min, height: min))
        return frames
    }
}

public class FMMosaicLayoutCopyBlock3: SquareMosaicBlock {
    
    public func blockFrames() -> Int {
        return 5
    }
    
    public func blockFrames(origin: CGFloat, side: CGFloat) -> [CGRect] {
        let min = side / 4.0
        let max = side - min - min
        var frames = [CGRect]()
        frames.append(CGRect(x: 0, y: origin, width: min, height: min))
        frames.append(CGRect(x: 0, y: origin + min, width: min, height: min))
        frames.append(CGRect(x: min, y: origin, width: min, height: min))
        frames.append(CGRect(x: min, y: origin + min, width: min, height: min))
        frames.append(CGRect(x: max, y: origin, width: max, height: max))
        return frames
    }
}