├── Pod
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── FMMosaicLayout.h
│ └── FMMosaicLayout.m
├── Example
├── Tests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── Tests.m
│ ├── Tests-Prefix.pch
│ └── Tests-Info.plist
├── FMMosaicLayout
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── Images.xcassets
│ │ ├── back.imageset
│ │ │ ├── back.png
│ │ │ └── Contents.json
│ │ ├── city.imageset
│ │ │ ├── city.png
│ │ │ └── Contents.json
│ │ ├── game.imageset
│ │ │ ├── game.png
│ │ │ └── Contents.json
│ │ ├── birds.imageset
│ │ │ ├── birds.png
│ │ │ └── Contents.json
│ │ ├── bridge.imageset
│ │ │ ├── bridge.png
│ │ │ └── Contents.json
│ │ ├── leaves.imageset
│ │ │ ├── leaves.png
│ │ │ └── Contents.json
│ │ ├── stars.imageset
│ │ │ ├── stars.png
│ │ │ └── Contents.json
│ │ ├── stream.imageset
│ │ │ ├── stream.png
│ │ │ └── Contents.json
│ │ ├── sunset.imageset
│ │ │ ├── sunset.png
│ │ │ └── Contents.json
│ │ ├── waves.imageset
│ │ │ ├── waves.png
│ │ │ └── Contents.json
│ │ ├── balcony.imageset
│ │ │ ├── balcony.png
│ │ │ └── Contents.json
│ │ ├── ceiling.imageset
│ │ │ ├── ceiling.png
│ │ │ └── Contents.json
│ │ ├── sitting.imageset
│ │ │ ├── sitting.png
│ │ │ └── Contents.json
│ │ ├── cityscape.imageset
│ │ │ ├── cityscape.png
│ │ │ └── Contents.json
│ │ ├── mountains.imageset
│ │ │ ├── mountains.png
│ │ │ └── Contents.json
│ │ ├── two-birds.imageset
│ │ │ ├── two-birds.png
│ │ │ └── Contents.json
│ │ ├── mountain-tops.imageset
│ │ │ ├── mountain-tops.png
│ │ │ └── Contents.json
│ │ ├── snowy-mountains.imageset
│ │ │ ├── snowy-mountains.png
│ │ │ └── Contents.json
│ │ ├── LaunchImage.launchimage
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── FMMosaicLayout-Prefix.pch
│ ├── FMMosaicLayout-Info.plist
│ ├── FMMosaicCollectionViewController.h
│ ├── FMAppDelegate.h
│ ├── FMFooterView.h
│ ├── FMHeaderView.h
│ ├── main.m
│ ├── FMMosaicCellView.h
│ ├── FMFooterView.m
│ ├── FMHeaderView.m
│ ├── FMAppDelegate.m
│ ├── FMMosaicCellView.m
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Example.storyboard
│ ├── FMFooterView.xib
│ ├── FMHeaderView.xib
│ └── FMMosaicCollectionViewController.m
├── FMMosaicLayout.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── FMMosaicLayout-Example.xcscheme
│ └── project.pbxproj
├── Podfile
├── Podfile.lock
└── FMMosaicLayout.xcworkspace
│ └── contents.xcworkspacedata
├── .gitignore
├── .travis.yml
├── FMMosaicLayout.podspec
├── LICENSE
└── README.md
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/back.imageset/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/back.imageset/back.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/city.imageset/city.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/city.imageset/city.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/game.imageset/game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/game.imageset/game.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/birds.imageset/birds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/birds.imageset/birds.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/bridge.imageset/bridge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/bridge.imageset/bridge.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/leaves.imageset/leaves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/leaves.imageset/leaves.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/stars.imageset/stars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/stars.imageset/stars.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/stream.imageset/stream.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/stream.imageset/stream.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/sunset.imageset/sunset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/sunset.imageset/sunset.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/waves.imageset/waves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/waves.imageset/waves.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/balcony.imageset/balcony.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/balcony.imageset/balcony.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/ceiling.imageset/ceiling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/ceiling.imageset/ceiling.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/sitting.imageset/sitting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/sitting.imageset/sitting.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/cityscape.imageset/cityscape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/cityscape.imageset/cityscape.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/mountains.imageset/mountains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/mountains.imageset/mountains.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/two-birds.imageset/two-birds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/two-birds.imageset/two-birds.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/mountain-tops.imageset/mountain-tops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/mountain-tops.imageset/mountain-tops.png
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/snowy-mountains.imageset/snowy-mountains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmitech/FMMosaicLayout/HEAD/Example/FMMosaicLayout/Images.xcassets/snowy-mountains.imageset/snowy-mountains.png
--------------------------------------------------------------------------------
/Example/Tests/Tests.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicLayoutTests.m
3 | // FMMosaicLayoutTests
4 | //
5 | // Created by JVillella on 02/10/2015.
6 | // Copyright (c) 2014 JVillella. All rights reserved.
7 | //
8 |
9 | ${TEST_EXAMPLE}
10 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every test case source file.
5 | //
6 |
7 | #ifdef __OBJC__
8 |
9 |
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | target 'FMMosaicLayout', :exclusive => true do
4 | pod "FMMosaicLayout", :path => "../"
5 | end
6 |
7 | target 'Tests', :exclusive => true do
8 | pod "FMMosaicLayout", :path => "../"
9 | end
10 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - FMMosaicLayout (0.1.1)
3 |
4 | DEPENDENCIES:
5 | - FMMosaicLayout (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | FMMosaicLayout:
9 | :path: ../
10 |
11 | SPEC CHECKSUMS:
12 | FMMosaicLayout: 54c5e40fa93cdfc1f245bea9d59ce6faa27fbfea
13 |
14 | COCOAPODS: 0.36.0.rc.1
15 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "back.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/city.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "city.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/game.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "game.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicLayout-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/birds.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "birds.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/bridge.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "bridge.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/leaves.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "leaves.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/stars.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "stars.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/stream.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "stream.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/sunset.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "sunset.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/waves.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "waves.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/balcony.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "balcony.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/ceiling.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "ceiling.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/cityscape.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "cityscape.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/mountains.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "mountains.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/sitting.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "sitting.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/two-birds.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "two-birds.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/mountain-tops.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "mountain-tops.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/snowy-mountains.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "snowy-mountains.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac
2 | .DS_Store
3 |
4 | # Xcode
5 | #
6 | build/
7 | *.pbxuser
8 | !default.pbxuser
9 | *.mode1v3
10 | !default.mode1v3
11 | *.mode2v3
12 | !default.mode2v3
13 | *.perspectivev3
14 | !default.perspectivev3
15 | xcuserdata
16 | *.xccheckout
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 | *.xcuserstate
22 |
23 | # CocoaPods
24 | #
25 | # We recommend against adding the Pods directory to your .gitignore. However
26 | # you should judge for yourself, the pros and cons are mentioned at:
27 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
28 | #
29 | Pods/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | language: objective-c
6 | # cache: cocoapods
7 | # podfile: Example/Podfile
8 | # before_install:
9 | # - gem install cocoapods # Since Travis is not always on latest version
10 | # - pod install --project-directory=Example
11 | install:
12 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
13 | script:
14 | - set -o pipefail && xcodebuild test -workspace Example/FMMosaicLayout.xcworkspace -scheme FMMosaicLayout-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c
15 | - pod lib lint --quick
16 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/FMMosaicLayout.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "FMMosaicLayout"
3 | s.version = "0.1.4"
4 | s.summary = "A drop-in mosaic collection view layout with a focus on simple customizations."
5 | s.homepage = "https://github.com/fmitech/FMMosaicLayout"
6 | s.screenshots = ["http://fmitech.github.io/FMMosaicLayout/Screenshots/portrait-1.png",
7 | "http://fmitech.github.io/FMMosaicLayout/Screenshots/portrait-2.png",
8 | "http://fmitech.github.io/FMMosaicLayout/Screenshots/portrait-3.png",
9 | "http://fmitech.github.io/FMMosaicLayout/Screenshots/landscape.png",
10 | "http://fmitech.github.io/FMMosaicLayout/Screenshots/fmmosaiclayout.gif"]
11 | s.license = 'MIT'
12 | s.author = { "JVillella" => "julian.villella@hotmail.com" }
13 | s.source = { :git => "https://github.com/fmitech/FMMosaicLayout.git", :tag => s.version.to_s }
14 |
15 | s.platform = :ios, '7.0'
16 | s.requires_arc = true
17 |
18 | s.source_files = 'Pod/Classes'
19 | end
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Fluid Media. All rights reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "ipad",
6 | "minimum-system-version" : "7.0",
7 | "extent" : "full-screen",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "landscape",
12 | "idiom" : "ipad",
13 | "minimum-system-version" : "7.0",
14 | "extent" : "full-screen",
15 | "scale" : "1x"
16 | },
17 | {
18 | "orientation" : "landscape",
19 | "idiom" : "ipad",
20 | "minimum-system-version" : "7.0",
21 | "extent" : "full-screen",
22 | "scale" : "2x"
23 | },
24 | {
25 | "orientation" : "portrait",
26 | "idiom" : "iphone",
27 | "minimum-system-version" : "7.0",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "minimum-system-version" : "7.0",
34 | "subtype" : "retina4",
35 | "scale" : "2x"
36 | },
37 | {
38 | "orientation" : "portrait",
39 | "idiom" : "ipad",
40 | "minimum-system-version" : "7.0",
41 | "extent" : "full-screen",
42 | "scale" : "1x"
43 | }
44 | ],
45 | "info" : {
46 | "version" : 1,
47 | "author" : "xcode"
48 | }
49 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicLayout-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.fluidmedia.$(PRODUCT_NAME:rfc1034identifier)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 0.1.4
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 5
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Example
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicCollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicCollectionViewController.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @interface FMMosaicCollectionViewController : UICollectionViewController
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMAppDelegate.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @interface FMAppDelegate : UIResponder
27 |
28 | @property (strong, nonatomic) UIWindow *window;
29 |
30 | @end
31 |
32 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMFooterView.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMFooterView.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-04-01.
6 | // Copyright (c) 2015 JVillella. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @interface FMFooterView : UICollectionReusableView
27 |
28 | + (NSString *)reuseIdentifier;
29 |
30 | @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMHeaderView.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-04-01.
6 | // Copyright (c) 2015 JVillella. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @interface FMHeaderView : UICollectionReusableView
27 |
28 | + (NSString *)reuseIdentifier;
29 |
30 | @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 | #import "FMAppDelegate.h"
28 |
29 | int main(int argc, char * argv[]) {
30 | @autoreleasepool {
31 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([FMAppDelegate class]));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicCellView.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicCellView.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @interface FMMosaicCellView : UICollectionViewCell
27 |
28 | + (NSString *)reuseIdentifier;
29 |
30 | @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
31 | @property (weak, nonatomic) IBOutlet UIImageView *imageView;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMFooterView.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMFooterView.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-04-01.
6 | // Copyright (c) 2015 JVillella. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMFooterView.h"
27 |
28 | static NSString* const kFMFooterViewReuseIdentifier = @"FMFooterViewReuseIdentifier";
29 |
30 | @implementation FMFooterView
31 |
32 | + (NSString *)reuseIdentifier {
33 | return kFMFooterViewReuseIdentifier;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMHeaderView.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-04-01.
6 | // Copyright (c) 2015 JVillella. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMHeaderView.h"
27 |
28 | static NSString* const kFMHeaderViewReuseIdentifier = @"FMHeaderViewReuseIdentifier";
29 |
30 | @implementation FMHeaderView
31 |
32 | + (NSString *)reuseIdentifier {
33 | return kFMHeaderViewReuseIdentifier;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMAppDelegate.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMAppDelegate.h"
27 |
28 | @implementation FMAppDelegate
29 |
30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
31 | return YES;
32 | }
33 |
34 | - (void)applicationWillResignActive:(UIApplication *)application {}
35 |
36 | - (void)applicationDidEnterBackground:(UIApplication *)application {}
37 |
38 | - (void)applicationWillEnterForeground:(UIApplication *)application {}
39 |
40 | - (void)applicationDidBecomeActive:(UIApplication *)application {}
41 |
42 | - (void)applicationWillTerminate:(UIApplication *)application {}
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/Pod/Classes/FMMosaicLayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicLayout.h
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | @class FMMosaicLayout;
27 |
28 | typedef NS_ENUM(NSUInteger, FMMosaicCellSize) {
29 | FMMosaicCellSizeSmall,
30 | FMMosaicCellSizeBig
31 | };
32 |
33 | @protocol FMMosaicLayoutDelegate
34 |
35 | - (NSInteger)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout numberOfColumnsInSection:(NSInteger)section;
36 |
37 | @optional
38 |
39 | - (FMMosaicCellSize)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout mosaicCellSizeForItemAtIndexPath:(NSIndexPath *)indexPath;
40 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
41 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout interitemSpacingForSectionAtIndex:(NSInteger)section;
42 |
43 | // Header/Footer
44 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
45 | heightForHeaderInSection:(NSInteger)section;
46 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
47 | heightForFooterInSection:(NSInteger)section;
48 | - (BOOL)headerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView
49 | layout:(FMMosaicLayout *)collectionViewLayout;
50 | - (BOOL)footerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView
51 | layout:(FMMosaicLayout *)collectionViewLayout;
52 |
53 | @end
54 |
55 | @interface FMMosaicLayout : UICollectionViewLayout
56 |
57 | // Not used, just for backwards compatability
58 | @property (nonatomic, weak) id delegate;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicCellView.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicCellView.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMMosaicCellView.h"
27 |
28 | static NSString* const kFMMosaicCellViewReuseIdentifier = @"FMMosaicCellViewReuseIdentifier";
29 |
30 | @interface FMMosaicCellView ()
31 |
32 | @property (weak, nonatomic) IBOutlet UIView *overlayView;
33 |
34 | @end
35 |
36 | @implementation FMMosaicCellView
37 |
38 | + (NSString *)reuseIdentifier {
39 | return kFMMosaicCellViewReuseIdentifier;
40 | }
41 |
42 | - (void)awakeFromNib {
43 | UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
44 | longPressGesture.minimumPressDuration = 0.0;
45 | longPressGesture.delegate = self;
46 | longPressGesture.cancelsTouchesInView = NO;
47 | [self addGestureRecognizer:longPressGesture];
48 | }
49 |
50 | - (void)onLongPress:(UILongPressGestureRecognizer *)longPressGestureRecognizer {
51 | if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan) {
52 | [UIView animateWithDuration:0.2 delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseOut animations:^{
53 | self.transform = CGAffineTransformMakeScale(0.9, 0.9);
54 | self.overlayView.alpha = 0.35;
55 | } completion:nil];
56 |
57 | } else {
58 | [UIView animateWithDuration:0.2 delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseOut animations:^{
59 | self.transform = CGAffineTransformIdentity;
60 | self.overlayView.alpha = 0.0;
61 | } completion:nil];
62 | }
63 | }
64 |
65 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
66 | return YES;
67 | }
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout.xcodeproj/xcshareddata/xcschemes/FMMosaicLayout-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/JVillella/FMMosaicLayout)
2 | [](http://cocoadocs.org/docsets/FMMosaicLayout)
3 | [](http://cocoadocs.org/docsets/FMMosaicLayout)
4 | [](http://cocoadocs.org/docsets/FMMosaicLayout)
5 |
6 | FMMosaicLayout is a mosiac collection view layout. There are a great number of media-based iOS applications that use `UICollectionViewFlowLayout` without any modifications. This lends itself to boring presentation, and unengaging interaction. FMMosaicLayout is a step in the right direction. Simply add this pod to your project, set your preferences and it will layout out your collection view cells in pretty mosaics. The algorithm behind this got its inspiration from this [blog post](http://blog.vjeux.com/2012/image/image-layout-algorithm-facebook.html).
7 |
8 | 
9 |
10 | ## Usage
11 |
12 | FMMosaicLayout is very easy to use. Below is all you need to get going.
13 |
14 | ```objective-c
15 | - (void)viewDidLoad {
16 | ...
17 |
18 | FMMosaicLayout *mosaicLayout = [[FMMosaicLayout alloc] init];
19 | self.collectionView.collectionViewLayout = mosaicLayout;
20 |
21 | ...
22 | }
23 |
24 | #pragma mark
25 |
26 | - (NSInteger)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
27 | numberOfColumnsInSection:(NSInteger)section {
28 |
29 | return 2; // Or any number of your choosing.
30 | }
31 | ```
32 |
33 | It's also possible to set the layout via Interface Builder. To see a complete example implementation. Clone the repo, and run `pod install` from the Example directory. Then open up `Example/FMMosaicLayout.xcworkspace`.
34 |
35 | ## Customization
36 |
37 | In addition to the required protocol method `collectionView:layout:numberOfColumnsInSection:`, there are several optional methods you can implement from `FMMosaicLayoutDelegate`. You can see them in action in the example project.
38 |
39 | ##### Mosaic Cell Size
40 |
41 | ```objective-c
42 | - (FMMosaicCellSize)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
43 | mosaicCellSizeForItemAtIndexPath:(NSIndexPath *)indexPath;
44 | ```
45 |
46 | This allows you to specify when you want to place a large or small mosaic cell.
47 |
48 | ##### Section Insets
49 | ```objective-c
50 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
51 | insetForSectionAtIndex:(NSInteger)section;
52 | ```
53 |
54 | Here you can specify a custom `UIEdgeInsets` for each section.
55 |
56 | ##### Interitem Spacing
57 |
58 | ```objective-c
59 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
60 | interitemSpacingForSectionAtIndex:(NSInteger)section;
61 | ```
62 |
63 | Here you can specify the spacing between cells.
64 |
65 | ##### Header and Footer Support
66 |
67 | Below are the optional methods you can make use of to customize your headers and footers. The first methods are to set the height of your header/footers.
68 |
69 | ```objective-c
70 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
71 | heightForHeaderInSection:(NSInteger)section;
72 |
73 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
74 | heightForFooterInSection:(NSInteger)section;
75 | ```
76 |
77 | If you want your header and/or to overlay your mosaic cells implement the following methods below in your delegate and have them return `YES`. The default is `NO`.
78 |
79 | ```objective-c
80 | - (BOOL)headerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView
81 | layout:(FMMosaicLayout *)collectionViewLayout;
82 |
83 | - (BOOL)footerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView
84 | layout:(FMMosaicLayout *)collectionViewLayout;
85 | ```
86 |
87 | ## Installation
88 |
89 | FMMosaicLayout is available through [CocoaPods](http://cocoapods.org). To install
90 | it, simply add the following line to your Podfile:
91 |
92 | ```ruby
93 | pod "FMMosaicLayout"
94 | ```
95 |
96 | ## License
97 |
98 | FMMosaicLayout is available under the MIT license. See the LICENSE file for more info.
99 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMFooterView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/Base.lproj/Example.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout/FMMosaicCollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicCollectionViewController.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMMosaicCollectionViewController.h"
27 | #import "FMMosaicCellView.h"
28 | #import "FMMosaicLayout.h"
29 | #import "FMHeaderView.h"
30 | #import "FMFooterView.h"
31 |
32 | static const CGFloat kFMHeaderFooterHeight = 44.0;
33 | static const NSInteger kFMMosaicColumnCount = 2;
34 |
35 | @interface FMMosaicCollectionViewController ()
36 |
37 | @property (nonatomic, strong) NSArray *stockImages;
38 |
39 | @end
40 |
41 | @implementation FMMosaicCollectionViewController
42 |
43 | - (void)viewDidLoad {
44 | [super viewDidLoad];
45 | self.collectionView.backgroundColor = [UIColor blackColor];
46 |
47 | [self.collectionView registerNib:[UINib nibWithNibName:@"FMHeaderView" bundle:nil]
48 | forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
49 | withReuseIdentifier:[FMHeaderView reuseIdentifier]];
50 |
51 | [self.collectionView registerNib:[UINib nibWithNibName:@"FMFooterView" bundle:nil]
52 | forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
53 | withReuseIdentifier:[FMFooterView reuseIdentifier]];
54 |
55 | [self adjustContentInsets];
56 | }
57 |
58 | - (void)adjustContentInsets {
59 | UIEdgeInsets insets = UIEdgeInsetsMake([UIApplication sharedApplication].statusBarFrame.size.height, 0, 0, 0);
60 | self.collectionView.contentInset = insets;
61 | self.collectionView.scrollIndicatorInsets = insets;
62 | }
63 |
64 | #pragma mark
65 |
66 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
67 | return 3;
68 | }
69 |
70 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
71 | switch (section) {
72 | case 0: return 66;
73 | case 1: return 123;
74 | }
75 | return 31;
76 | }
77 |
78 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
79 | FMMosaicCellView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[FMMosaicCellView reuseIdentifier] forIndexPath:indexPath];
80 |
81 | // Configure the cell
82 | cell.titleLabel.text = [NSString stringWithFormat:@"%ld", (long)indexPath.item + 1];
83 | cell.imageView.image = self.stockImages[indexPath.item % self.stockImages.count];
84 |
85 | return cell;
86 | }
87 |
88 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
89 | viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
90 |
91 | UICollectionReusableView *reusableView = nil;
92 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
93 | FMHeaderView *headerView = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind
94 | withReuseIdentifier:[FMHeaderView reuseIdentifier] forIndexPath:indexPath];
95 |
96 | headerView.titleLabel.text = [NSString stringWithFormat:@"SECTION %ld", (long)indexPath.section + 1];
97 | reusableView = headerView;
98 |
99 | } else if([kind isEqualToString:UICollectionElementKindSectionFooter]) {
100 | FMFooterView *footerView = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind
101 | withReuseIdentifier:[FMFooterView reuseIdentifier] forIndexPath:indexPath];
102 |
103 | NSInteger assetCount = [self collectionView:self.collectionView numberOfItemsInSection:indexPath.section];
104 | footerView.titleLabel.text = assetCount == 1 ? @"1 ASSET" : [NSString stringWithFormat:@"%ld ASSETS", (long)assetCount];
105 | reusableView = footerView;
106 | }
107 |
108 | return reusableView;
109 | }
110 |
111 | #pragma mark
112 |
113 | - (NSInteger)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
114 | numberOfColumnsInSection:(NSInteger)section {
115 | return kFMMosaicColumnCount;
116 | }
117 |
118 | - (FMMosaicCellSize)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
119 | mosaicCellSizeForItemAtIndexPath:(NSIndexPath *)indexPath {
120 | return (indexPath.item % 12 == 0) ? FMMosaicCellSizeBig : FMMosaicCellSizeSmall;
121 | }
122 |
123 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
124 | insetForSectionAtIndex:(NSInteger)section {
125 | return UIEdgeInsetsMake(5.0, 5.0, 5.0, 5.0);
126 | }
127 |
128 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout
129 | interitemSpacingForSectionAtIndex:(NSInteger)section {
130 | return 2.0;
131 | }
132 |
133 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
134 | heightForHeaderInSection:(NSInteger)section {
135 | return kFMHeaderFooterHeight;
136 | }
137 |
138 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
139 | heightForFooterInSection:(NSInteger)section {
140 | return kFMHeaderFooterHeight;
141 | }
142 |
143 | - (BOOL)headerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout {
144 | return YES;
145 | }
146 |
147 | - (BOOL)footerShouldOverlayContentInCollectionView:(UICollectionView *)collectionView layout:(FMMosaicLayout *)collectionViewLayout {
148 | return YES;
149 | }
150 |
151 | #pragma mark - Accessors
152 |
153 | - (NSArray *)stockImages {
154 | if (!_stockImages) {
155 | _stockImages = @[
156 | [UIImage imageNamed:@"back"],
157 | [UIImage imageNamed:@"balcony"],
158 | [UIImage imageNamed:@"birds"],
159 | [UIImage imageNamed:@"bridge"],
160 | [UIImage imageNamed:@"ceiling"],
161 | [UIImage imageNamed:@"city"],
162 | [UIImage imageNamed:@"cityscape"],
163 | [UIImage imageNamed:@"game"],
164 | [UIImage imageNamed:@"leaves"],
165 | [UIImage imageNamed:@"mountain-tops"],
166 | [UIImage imageNamed:@"mountains"],
167 | [UIImage imageNamed:@"sitting"],
168 | [UIImage imageNamed:@"snowy-mountains"],
169 | [UIImage imageNamed:@"stars"],
170 | [UIImage imageNamed:@"stream"],
171 | [UIImage imageNamed:@"sunset"],
172 | [UIImage imageNamed:@"two-birds"],
173 | [UIImage imageNamed:@"waves"]
174 | ];
175 | }
176 | return _stockImages;
177 | }
178 |
179 | #pragma mark - Status Bar
180 |
181 | - (UIStatusBarStyle)preferredStatusBarStyle {
182 | return UIStatusBarStyleLightContent;
183 | }
184 |
185 | @end
186 |
--------------------------------------------------------------------------------
/Pod/Classes/FMMosaicLayout.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMMosaicLayout.m
3 | // FMMosaicLayout
4 | //
5 | // Created by Julian Villella on 2015-01-30.
6 | // Copyright (c) 2015 Fluid Media. All rights reserved.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import "FMMosaicLayout.h"
27 |
28 | static const NSInteger kFMDefaultNumberOfColumnsInSection = 2;
29 | static const FMMosaicCellSize kFMDefaultCellSize = FMMosaicCellSizeSmall;
30 | static const FMMosaicCellSize kFMDefaultHeaderFooterHeight = 0.0;
31 | static const BOOL kFMDefaultHeaderShouldOverlayContent = NO;
32 | static const BOOL kFMDefaultFooterShouldOverlayContent = NO;
33 |
34 | @interface FMMosaicLayout ()
35 |
36 | /**
37 | * A 2D array holding an array of columns heights for each section
38 | */
39 | @property (nonatomic, strong) NSMutableArray *columnHeightsPerSection;
40 |
41 | /**
42 | * Array of cached layout attributes for each cell
43 | */
44 | @property (nonatomic, strong) NSMutableDictionary *cellLayoutAttributes;
45 |
46 | /**
47 | * Array of cached layout attributes for each supplementary view (only headers and footer kinds are currently supported)
48 | */
49 | @property (nonatomic, strong) NSMutableDictionary *supplementaryLayoutAttributes;
50 |
51 | @end
52 |
53 | @implementation FMMosaicLayout
54 |
55 | - (void)prepareLayout {
56 | [super prepareLayout];
57 |
58 | [self resetLayoutState];
59 |
60 | // Calculate layout attritbutes in each section
61 | for (NSInteger sectionIndex = 0; sectionIndex < [self.collectionView numberOfSections]; sectionIndex++) {
62 |
63 | CGFloat interitemSpacing = [self interitemSpacingAtSection:sectionIndex];
64 |
65 | // Add top section insets
66 | [self growColumnHeightsBy:[self insetForSectionAtIndex:sectionIndex].top section:sectionIndex];
67 |
68 | // Adds header view
69 | UICollectionViewLayoutAttributes *headerLayoutAttribute =
70 | [self addLayoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
71 | indexPath:[NSIndexPath indexPathForItem:0 inSection:sectionIndex]];
72 |
73 | if (![self headerShouldOverlayContent]) {
74 | [self growColumnHeightsBy:headerLayoutAttribute.frame.size.height + interitemSpacing section:sectionIndex];
75 | }
76 |
77 | // Calculate cell attributes in each section
78 | NSMutableArray *smallMosaicCellIndexPathsBuffer = [[NSMutableArray alloc] initWithCapacity:2];
79 | for (NSInteger cellIndex = 0; cellIndex < [self.collectionView numberOfItemsInSection:sectionIndex]; cellIndex++) {
80 |
81 | NSIndexPath *cellIndexPath = [NSIndexPath indexPathForItem:cellIndex inSection:sectionIndex];
82 | FMMosaicCellSize mosaicCellSize = [self mosaicCellSizeForItemAtIndexPath:cellIndexPath];
83 | NSInteger indexOfShortestColumn = [self indexOfShortestColumnInSection:sectionIndex]; // must be recalculated every time a new cell is added
84 |
85 | if (mosaicCellSize == FMMosaicCellSizeBig) {
86 | // Add big cell to shortest column, calculate layout attributes, and recalculate column height now that it's been added
87 | UICollectionViewLayoutAttributes *layoutAttributes = [self addBigMosaicLayoutAttributesForIndexPath:cellIndexPath inColumn:indexOfShortestColumn];
88 | CGFloat columnHeight = [self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] floatValue];
89 | self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] = @(columnHeight + layoutAttributes.frame.size.height + interitemSpacing);
90 |
91 | } else if(mosaicCellSize == FMMosaicCellSizeSmall) {
92 | [smallMosaicCellIndexPathsBuffer addObject:cellIndexPath];
93 |
94 | // Wait until small cell buffer is full (widths add up to one big cell), then add small cells to column heights array and layout attributes
95 | if(smallMosaicCellIndexPathsBuffer.count >= 2) {
96 | UICollectionViewLayoutAttributes *layoutAttributes = [self addSmallMosaicLayoutAttributesForIndexPath:smallMosaicCellIndexPathsBuffer[0]
97 | inColumn:indexOfShortestColumn bufferIndex:0];
98 | [self addSmallMosaicLayoutAttributesForIndexPath:smallMosaicCellIndexPathsBuffer[1] inColumn:indexOfShortestColumn bufferIndex:1];
99 |
100 | // Add to small cells to shortest column, and recalculate column height now that they've been added
101 | CGFloat columnHeight = [self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] floatValue];
102 | self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] = @(columnHeight + layoutAttributes.frame.size.height + interitemSpacing);
103 | [smallMosaicCellIndexPathsBuffer removeAllObjects];
104 | }
105 | }
106 | }
107 |
108 | // Handle remaining cells that didn't fill the buffer
109 | if (smallMosaicCellIndexPathsBuffer.count > 0) {
110 | NSInteger indexOfShortestColumn = [self indexOfShortestColumnInSection:sectionIndex];
111 | UICollectionViewLayoutAttributes *layoutAttributes = [self addSmallMosaicLayoutAttributesForIndexPath:smallMosaicCellIndexPathsBuffer[0]
112 | inColumn:indexOfShortestColumn bufferIndex:0];
113 |
114 | // Add to small cells to shortest column, and recalculate column height now that they've been added
115 | CGFloat columnHeight = [self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] floatValue];
116 | self.columnHeightsPerSection[sectionIndex][indexOfShortestColumn] = @(columnHeight + layoutAttributes.frame.size.height + interitemSpacing);
117 | [smallMosaicCellIndexPathsBuffer removeAllObjects];
118 | }
119 |
120 | // Adds footer view
121 | UICollectionViewLayoutAttributes *footerLayoutAttribute =
122 | [self addLayoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter
123 | indexPath:[NSIndexPath indexPathForItem:1 inSection:sectionIndex]];
124 |
125 | if (![self footerShouldOverlayContent]) {
126 | [self growColumnHeightsBy:footerLayoutAttribute.frame.size.height section:sectionIndex];
127 | }
128 |
129 | // Add bottom section insets, and remove extra added inset
130 | [self growColumnHeightsBy:[self insetForSectionAtIndex:sectionIndex].bottom section:sectionIndex];
131 | }
132 | }
133 |
134 | // Calculate and return all layout attributes in a given rect
135 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
136 | NSMutableArray *attributesInRect = [[NSMutableArray alloc] initWithCapacity:self.cellLayoutAttributes.count];
137 |
138 | // Cells
139 | [self.cellLayoutAttributes enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *stop) {
140 | if(CGRectIntersectsRect(rect, attributes.frame)){
141 | [attributesInRect addObject:attributes];
142 | }
143 | }];
144 |
145 | // Supplementary views
146 | [self.supplementaryLayoutAttributes enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *stop) {
147 | if(CGRectIntersectsRect(rect, attributes.frame)){
148 | [attributesInRect addObject:attributes];
149 | }
150 | }];
151 |
152 | return attributesInRect;
153 | }
154 |
155 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
156 | return [self.cellLayoutAttributes objectForKey:indexPath];
157 | }
158 |
159 | - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
160 | return [self.supplementaryLayoutAttributes objectForKey:indexPath];
161 | }
162 |
163 | // Content size is the width of the collection view, and the height of all sections combined
164 | - (CGSize)collectionViewContentSize {
165 | CGFloat width = [self collectionViewContentWidth];
166 | __block CGFloat height = 0.0;
167 |
168 | [self.columnHeightsPerSection enumerateObjectsUsingBlock:^(NSArray *columnHeights, NSUInteger sectionIndex, BOOL *stop) {
169 | NSInteger indexOfTallestColumn = [self indexOfTallestColumnInSection:sectionIndex];
170 | height += [columnHeights[indexOfTallestColumn] floatValue];
171 | }];
172 |
173 | return CGSizeMake(width, height);
174 | }
175 |
176 | - (CGFloat)collectionViewContentWidth {
177 | return self.collectionView.bounds.size.width;
178 | }
179 |
180 | #pragma mark - Orientation
181 |
182 | - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
183 | CGRect oldBounds = self.collectionView.bounds;
184 |
185 | // Invalidate if the bounds has changed
186 | if (!CGSizeEqualToSize(oldBounds.size, newBounds.size)) {
187 | [self prepareLayout];
188 | return YES;
189 | }
190 | return NO;
191 | }
192 |
193 | - (void)resetLayoutState {
194 | [self.columnHeightsPerSection removeAllObjects];
195 | _columnHeightsPerSection = nil;
196 |
197 | [self.cellLayoutAttributes removeAllObjects];
198 | _cellLayoutAttributes = nil;
199 |
200 | [self.supplementaryLayoutAttributes removeAllObjects];
201 | _supplementaryLayoutAttributes = nil;
202 | }
203 |
204 | #pragma mark - Accessors
205 |
206 | - (NSArray *)columnHeightsPerSection {
207 | if (!_columnHeightsPerSection) {
208 | NSInteger sectionCount = [self.collectionView numberOfSections];
209 | _columnHeightsPerSection = [[NSMutableArray alloc] initWithCapacity:sectionCount];
210 |
211 | for (NSInteger sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
212 | NSInteger numberOfColumnsInSection = [self numberOfColumnsInSection:sectionIndex];
213 | NSMutableArray *columnHeights = [[NSMutableArray alloc] initWithCapacity:numberOfColumnsInSection];
214 |
215 | for (NSInteger columnIndex = 0; columnIndex < numberOfColumnsInSection; columnIndex++) {
216 | [columnHeights addObject:@0];
217 | }
218 |
219 | [_columnHeightsPerSection addObject:columnHeights];
220 | }
221 | }
222 |
223 | return _columnHeightsPerSection;
224 | }
225 |
226 | - (NSMutableDictionary *)cellLayoutAttributes {
227 | if (!_cellLayoutAttributes) {
228 | _cellLayoutAttributes = [[NSMutableDictionary alloc] init];
229 | }
230 | return _cellLayoutAttributes;
231 | }
232 |
233 | - (NSMutableDictionary *)supplementaryLayoutAttributes {
234 | if (!_supplementaryLayoutAttributes) {
235 | _supplementaryLayoutAttributes = [[NSMutableDictionary alloc] init];
236 | }
237 | return _supplementaryLayoutAttributes;
238 | }
239 |
240 | #pragma mark - Helpers
241 |
242 | #pragma mark Layout Attributes Helpers
243 |
244 | // Calculates layout attributes for a small cell, adds to layout attributes array and returns it
245 | - (UICollectionViewLayoutAttributes *)addSmallMosaicLayoutAttributesForIndexPath:(NSIndexPath *)cellIndexPath
246 | inColumn:(NSInteger)column bufferIndex:(NSInteger)bufferIndex {
247 | UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:cellIndexPath];
248 | CGRect frame = [self mosaicCellRectWithSize:FMMosaicCellSizeSmall atIndexPath:cellIndexPath inColumn:column];
249 |
250 | // Account for first or second small mosaic cell
251 | CGFloat interitemSpacing = [self interitemSpacingAtSection:cellIndexPath.section];
252 | CGFloat cellWidth = [self cellHeightForMosaicSize:FMMosaicCellSizeSmall section:cellIndexPath.section];
253 | frame.origin.x += (cellWidth + interitemSpacing) * bufferIndex;
254 | layoutAttributes.frame = frame;
255 |
256 | [self.cellLayoutAttributes setObject:layoutAttributes forKey:cellIndexPath];
257 |
258 | return layoutAttributes;
259 | }
260 |
261 | // Calculates layout attributes for a big cell, adds to layout attributes array and returns it
262 | - (UICollectionViewLayoutAttributes *)addBigMosaicLayoutAttributesForIndexPath:(NSIndexPath *)cellIndexPath inColumn:(NSInteger)column {
263 | UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:cellIndexPath];
264 | CGRect frame = [self mosaicCellRectWithSize:FMMosaicCellSizeBig atIndexPath:cellIndexPath inColumn:column];
265 | layoutAttributes.frame = frame;
266 |
267 | [self.cellLayoutAttributes setObject:layoutAttributes forKey:cellIndexPath];
268 |
269 | return layoutAttributes;
270 | }
271 |
272 | - (CGRect)mosaicCellRectWithSize:(FMMosaicCellSize)mosaicCellSize atIndexPath:(NSIndexPath *)cellIndexPath inColumn:(NSInteger)column {
273 | NSInteger sectionIndex = cellIndexPath.section;
274 |
275 | CGFloat cellHeight = [self cellHeightForMosaicSize:mosaicCellSize section:sectionIndex];
276 | CGFloat cellWidth = cellHeight;
277 | CGFloat columnHeight = [self.columnHeightsPerSection[sectionIndex][column] floatValue];
278 |
279 | CGFloat originX = column * [self columnWidthInSection:sectionIndex];
280 | CGFloat originY = [self verticalOffsetForSection:sectionIndex] + columnHeight;
281 |
282 | // Factor in interitem spacing and insets
283 | UIEdgeInsets sectionInset = [self insetForSectionAtIndex:sectionIndex];
284 | CGFloat interitemSpacing = [self interitemSpacingAtSection:sectionIndex];
285 | originX += sectionInset.left;
286 | originX += column * interitemSpacing;
287 |
288 | return CGRectMake(originX, originY, cellWidth, cellHeight);
289 | }
290 |
291 | - (UICollectionViewLayoutAttributes *)addLayoutAttributesForSupplementaryViewOfKind:(NSString *)kind indexPath:(NSIndexPath *)indexPath {
292 | UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind withIndexPath:indexPath];
293 |
294 | UIEdgeInsets sectionInset = [self insetForSectionAtIndex:indexPath.section];
295 | CGFloat originX = sectionInset.left;
296 | CGFloat originY = [self verticalOffsetForSection:indexPath.section];
297 | CGFloat width = [self collectionViewContentWidth] - sectionInset.left - sectionInset.right;
298 | CGFloat height = 0.0;
299 |
300 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
301 | height = [self heightForHeaderAtSection:indexPath.section];
302 |
303 | } else if([kind isEqualToString:UICollectionElementKindSectionFooter]) {
304 | height = [self heightForFooterAtSection:indexPath.section];
305 | if ([self footerShouldOverlayContent]) {
306 | originY -= height;
307 | }
308 | }
309 |
310 | NSInteger tallestColumnIndex = [self indexOfTallestColumnInSection:indexPath.section];
311 | CGFloat sectionColumnHeight = [self.columnHeightsPerSection[indexPath.section][tallestColumnIndex] floatValue];
312 |
313 | layoutAttributes.frame = CGRectMake(originX, sectionColumnHeight + originY, width, height);
314 | layoutAttributes.zIndex = 1;
315 |
316 | [self.supplementaryLayoutAttributes setObject:layoutAttributes forKey:indexPath];
317 |
318 | return layoutAttributes;
319 | }
320 |
321 | #pragma mark Sizing Helpers
322 |
323 | - (CGFloat)cellHeightForMosaicSize:(FMMosaicCellSize)mosaicCellSize section:(NSInteger)section {
324 | CGFloat bigCellSize = [self columnWidthInSection:section];
325 | CGFloat interitemSpacing = [self interitemSpacingAtSection:section];
326 | return mosaicCellSize == FMMosaicCellSizeBig ? bigCellSize : (bigCellSize - interitemSpacing) / 2.0;
327 | }
328 |
329 | // The width of a column refers to the width of one FMMosaicCellSizeBig cell w/o interitem spacing
330 | - (CGFloat)columnWidthInSection:(NSInteger)section {
331 | UIEdgeInsets sectionInset = [self insetForSectionAtIndex:section];
332 | CGFloat combinedInteritemSpacing = ([self numberOfColumnsInSection:section] - 1) * [self interitemSpacingAtSection:section];
333 | CGFloat combinedColumnWidth = [self collectionViewContentWidth] - sectionInset.left - sectionInset.right - combinedInteritemSpacing;
334 |
335 | return combinedColumnWidth / [self numberOfColumnsInSection:section];
336 | }
337 |
338 | // The vertical position where this section begins
339 | - (CGFloat)verticalOffsetForSection:(NSInteger)section {
340 | CGFloat verticalOffset = 0.0;
341 |
342 | // Add up heights of all previous sections to get vertical position of this section
343 | for (NSInteger i = 0; i < section; i++) {
344 | NSInteger indexOfTallestColumn = [self indexOfTallestColumnInSection:i];
345 | CGFloat sectionHeight = [self.columnHeightsPerSection[i][indexOfTallestColumn] floatValue];
346 | verticalOffset += sectionHeight;
347 | }
348 |
349 | return verticalOffset;
350 | }
351 |
352 | - (void)growColumnHeightsBy:(CGFloat)increase section:(NSInteger)section {
353 | NSMutableArray *columnHeights = [self.columnHeightsPerSection objectAtIndex:section];
354 |
355 | for (int i = 0; i < columnHeights.count; i++) {
356 | columnHeights[i] = @([columnHeights[i] floatValue] + increase);
357 | }
358 | }
359 |
360 | #pragma mark Index Helpers
361 |
362 | - (NSInteger)indexOfShortestColumnInSection:(NSInteger)section {
363 | NSArray *columnHeights = [self.columnHeightsPerSection objectAtIndex:section];
364 |
365 | NSInteger indexOfShortestColumn = 0;
366 | for (int i = 1; i < columnHeights.count; i++) {
367 | if([columnHeights[i] floatValue] < [columnHeights[indexOfShortestColumn] floatValue])
368 | indexOfShortestColumn = i;
369 | }
370 |
371 | return indexOfShortestColumn;
372 | }
373 |
374 | - (NSInteger)indexOfTallestColumnInSection:(NSInteger)section {
375 | NSArray *columnHeights = [self.columnHeightsPerSection objectAtIndex:section];
376 |
377 | NSInteger indexOfTallestColumn = 0;
378 | for (int i = 1; i < columnHeights.count; i++) {
379 | if([columnHeights[i] floatValue] > [columnHeights[indexOfTallestColumn] floatValue])
380 | indexOfTallestColumn = i;
381 | }
382 |
383 | return indexOfTallestColumn;
384 | }
385 |
386 | #pragma mark - Delegate Wrappers
387 |
388 | - (NSInteger)numberOfColumnsInSection:(NSInteger)section {
389 | NSInteger columnCount = kFMDefaultNumberOfColumnsInSection;
390 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:numberOfColumnsInSection:)]) {
391 | columnCount = [self.delegate collectionView:self.collectionView layout:self numberOfColumnsInSection:section];
392 | }
393 | return columnCount;
394 | }
395 |
396 | - (FMMosaicCellSize)mosaicCellSizeForItemAtIndexPath:(NSIndexPath *)indexPath {
397 | FMMosaicCellSize cellSize = kFMDefaultCellSize;
398 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:mosaicCellSizeForItemAtIndexPath:)]) {
399 | cellSize = [self.delegate collectionView:self.collectionView layout:self mosaicCellSizeForItemAtIndexPath:indexPath];
400 | }
401 | return cellSize;
402 | }
403 |
404 | - (UIEdgeInsets)insetForSectionAtIndex:(NSInteger)section {
405 | UIEdgeInsets inset = UIEdgeInsetsZero;
406 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
407 | inset = [self.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
408 | }
409 | return inset;
410 | }
411 |
412 | - (CGFloat)interitemSpacingAtSection:(NSInteger)section {
413 | CGFloat interitemSpacing = 0.0;
414 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:interitemSpacingForSectionAtIndex:)]) {
415 | interitemSpacing = [self.delegate collectionView:self.collectionView layout:self interitemSpacingForSectionAtIndex:section];
416 | }
417 | return interitemSpacing;
418 | }
419 |
420 | - (CGFloat)heightForHeaderAtSection:(NSInteger)section {
421 | CGFloat height = kFMDefaultHeaderFooterHeight;
422 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:heightForHeaderInSection:)]) {
423 | height = [self.delegate collectionView:self.collectionView layout:self heightForHeaderInSection:section];
424 | }
425 | return height;
426 | }
427 |
428 | - (CGFloat)heightForFooterAtSection:(NSInteger)section {
429 | CGFloat height = kFMDefaultHeaderFooterHeight;
430 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:heightForFooterInSection:)]) {
431 | height = [self.delegate collectionView:self.collectionView layout:self heightForFooterInSection:section];
432 | }
433 | return height;
434 | }
435 |
436 | - (BOOL)headerShouldOverlayContent {
437 | CGFloat shouldOverlay = kFMDefaultHeaderShouldOverlayContent;
438 | if ([self.delegate respondsToSelector:@selector(headerShouldOverlayContentInCollectionView:layout:)]) {
439 | shouldOverlay = [self.delegate headerShouldOverlayContentInCollectionView:self.collectionView layout:self];
440 | }
441 | return shouldOverlay;
442 | }
443 |
444 | - (BOOL)footerShouldOverlayContent {
445 | CGFloat shouldOverlay = kFMDefaultFooterShouldOverlayContent;
446 | if ([self.delegate respondsToSelector:@selector(footerShouldOverlayContentInCollectionView:layout:)]) {
447 | shouldOverlay = [self.delegate footerShouldOverlayContentInCollectionView:self.collectionView layout:self];
448 | }
449 | return shouldOverlay;
450 | }
451 |
452 | // If layout delegate hasn't been provided, resort to collection view's delegate which is likely a UICollectionViewController
453 | - (id)delegate {
454 | return _delegate ? _delegate : (id)self.collectionView.delegate;
455 | }
456 |
457 | @end
458 |
--------------------------------------------------------------------------------
/Example/FMMosaicLayout.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 16C68EBB823B4316E125CD70 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF23CF08D3EBDE40465A3363 /* libPods-Tests.a */; };
11 | 4C5D8598233836885FB6D374 /* libPods-FMMosaicLayout.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E88784FB63092BC5C3699361 /* libPods-FMMosaicLayout.a */; };
12 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
13 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
14 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
15 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
16 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; };
17 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
18 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
19 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
20 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
21 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; };
22 | B952EA111ACC380700A979A6 /* FMFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = B952EA0F1ACC380700A979A6 /* FMFooterView.m */; };
23 | B952EA161ACC382600A979A6 /* FMHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = B952EA141ACC382600A979A6 /* FMHeaderView.m */; };
24 | B96097921AD4342D00EBD79A /* FMFooterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B96097901AD4342D00EBD79A /* FMFooterView.xib */; };
25 | B96097931AD4342D00EBD79A /* FMHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B96097911AD4342D00EBD79A /* FMHeaderView.xib */; };
26 | B986BA221A8A5F6000E4584D /* FMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B986BA1E1A8A5F6000E4584D /* FMAppDelegate.m */; };
27 | B986BA231A8A5F6000E4584D /* FMMosaicCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = B986BA1F1A8A5F6000E4584D /* FMMosaicCellView.m */; };
28 | B986BA241A8A5F6000E4584D /* FMMosaicCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B986BA201A8A5F6000E4584D /* FMMosaicCollectionViewController.m */; };
29 | B986BA251A8A5F6000E4584D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B986BA211A8A5F6000E4584D /* main.m */; };
30 | B986BA2A1A8A5F7D00E4584D /* Example.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B986BA261A8A5F7D00E4584D /* Example.storyboard */; };
31 | B986BA2B1A8A5F7D00E4584D /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B986BA281A8A5F7D00E4584D /* LaunchScreen.xib */; };
32 | /* End PBXBuildFile section */
33 |
34 | /* Begin PBXContainerItemProxy section */
35 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
36 | isa = PBXContainerItemProxy;
37 | containerPortal = 6003F582195388D10070C39A /* Project object */;
38 | proxyType = 1;
39 | remoteGlobalIDString = 6003F589195388D20070C39A;
40 | remoteInfo = FMMosaicLayout;
41 | };
42 | /* End PBXContainerItemProxy section */
43 |
44 | /* Begin PBXFileReference section */
45 | 0E432239394A4D76C39CDD75 /* FMMosaicLayout.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = FMMosaicLayout.podspec; path = ../FMMosaicLayout.podspec; sourceTree = ""; };
46 | 18DE6644CFE566A04570A623 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
47 | 271B5DC9EE27D3AF67E31CC1 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; };
48 | 564285136DBFDA264B2EA590 /* Pods-FMMosaicLayout.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMMosaicLayout.release.xcconfig"; path = "Pods/Target Support Files/Pods-FMMosaicLayout/Pods-FMMosaicLayout.release.xcconfig"; sourceTree = ""; };
49 | 57344976FD9A706AF9A5C0F6 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; };
50 | 6003F58A195388D20070C39A /* FMMosaicLayout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FMMosaicLayout.app; sourceTree = BUILT_PRODUCTS_DIR; };
51 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
52 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
53 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
54 | 6003F595195388D20070C39A /* FMMosaicLayout-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FMMosaicLayout-Info.plist"; sourceTree = ""; };
55 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
56 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
57 | 6003F59B195388D20070C39A /* FMMosaicLayout-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FMMosaicLayout-Prefix.pch"; sourceTree = ""; };
58 | 6003F59C195388D20070C39A /* FMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMAppDelegate.h; sourceTree = ""; };
59 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
60 | 6003F5AE195388D20070C39A /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
61 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
62 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; };
63 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
64 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; };
65 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; };
66 | 7605C3CD52D024CD64BFE751 /* Pods-FMMosaicLayout.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FMMosaicLayout.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FMMosaicLayout/Pods-FMMosaicLayout.debug.xcconfig"; sourceTree = ""; };
67 | 7CBBF3E3E5CC0B3DEF0EB910 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
68 | AF23CF08D3EBDE40465A3363 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
69 | B952EA0E1ACC380700A979A6 /* FMFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMFooterView.h; sourceTree = ""; };
70 | B952EA0F1ACC380700A979A6 /* FMFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMFooterView.m; sourceTree = ""; };
71 | B952EA131ACC382600A979A6 /* FMHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMHeaderView.h; sourceTree = ""; };
72 | B952EA141ACC382600A979A6 /* FMHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMHeaderView.m; sourceTree = ""; };
73 | B96097901AD4342D00EBD79A /* FMFooterView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FMFooterView.xib; sourceTree = ""; };
74 | B96097911AD4342D00EBD79A /* FMHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FMHeaderView.xib; sourceTree = ""; };
75 | B986BA1E1A8A5F6000E4584D /* FMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMAppDelegate.m; sourceTree = ""; };
76 | B986BA1F1A8A5F6000E4584D /* FMMosaicCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMMosaicCellView.m; sourceTree = ""; };
77 | B986BA201A8A5F6000E4584D /* FMMosaicCollectionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMMosaicCollectionViewController.m; sourceTree = ""; };
78 | B986BA211A8A5F6000E4584D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
79 | B986BA271A8A5F7D00E4584D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Example.storyboard; sourceTree = ""; };
80 | B986BA291A8A5F7D00E4584D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
81 | B986BA351A8A65AD00E4584D /* FMMosaicCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMMosaicCellView.h; sourceTree = ""; };
82 | B986BA361A8A65AD00E4584D /* FMMosaicCollectionViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMMosaicCollectionViewController.h; sourceTree = ""; };
83 | E88784FB63092BC5C3699361 /* libPods-FMMosaicLayout.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FMMosaicLayout.a"; sourceTree = BUILT_PRODUCTS_DIR; };
84 | /* End PBXFileReference section */
85 |
86 | /* Begin PBXFrameworksBuildPhase section */
87 | 6003F587195388D20070C39A /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
92 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
93 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
94 | 4C5D8598233836885FB6D374 /* libPods-FMMosaicLayout.a in Frameworks */,
95 | );
96 | runOnlyForDeploymentPostprocessing = 0;
97 | };
98 | 6003F5AB195388D20070C39A /* Frameworks */ = {
99 | isa = PBXFrameworksBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
103 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
104 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
105 | 16C68EBB823B4316E125CD70 /* libPods-Tests.a in Frameworks */,
106 | );
107 | runOnlyForDeploymentPostprocessing = 0;
108 | };
109 | /* End PBXFrameworksBuildPhase section */
110 |
111 | /* Begin PBXGroup section */
112 | 3C0722103454B1CA2A6B151F /* Pods */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 7605C3CD52D024CD64BFE751 /* Pods-FMMosaicLayout.debug.xcconfig */,
116 | 564285136DBFDA264B2EA590 /* Pods-FMMosaicLayout.release.xcconfig */,
117 | 57344976FD9A706AF9A5C0F6 /* Pods-Tests.debug.xcconfig */,
118 | 271B5DC9EE27D3AF67E31CC1 /* Pods-Tests.release.xcconfig */,
119 | );
120 | name = Pods;
121 | sourceTree = "";
122 | };
123 | 6003F581195388D10070C39A = {
124 | isa = PBXGroup;
125 | children = (
126 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
127 | 6003F593195388D20070C39A /* FMMosaicLayout */,
128 | 6003F5B5195388D20070C39A /* Tests */,
129 | 6003F58C195388D20070C39A /* Frameworks */,
130 | 6003F58B195388D20070C39A /* Products */,
131 | 3C0722103454B1CA2A6B151F /* Pods */,
132 | );
133 | sourceTree = "";
134 | };
135 | 6003F58B195388D20070C39A /* Products */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 6003F58A195388D20070C39A /* FMMosaicLayout.app */,
139 | 6003F5AE195388D20070C39A /* Tests.xctest */,
140 | );
141 | name = Products;
142 | sourceTree = "";
143 | };
144 | 6003F58C195388D20070C39A /* Frameworks */ = {
145 | isa = PBXGroup;
146 | children = (
147 | 6003F58D195388D20070C39A /* Foundation.framework */,
148 | 6003F58F195388D20070C39A /* CoreGraphics.framework */,
149 | 6003F591195388D20070C39A /* UIKit.framework */,
150 | 6003F5AF195388D20070C39A /* XCTest.framework */,
151 | E88784FB63092BC5C3699361 /* libPods-FMMosaicLayout.a */,
152 | AF23CF08D3EBDE40465A3363 /* libPods-Tests.a */,
153 | );
154 | name = Frameworks;
155 | sourceTree = "";
156 | };
157 | 6003F593195388D20070C39A /* FMMosaicLayout */ = {
158 | isa = PBXGroup;
159 | children = (
160 | B952EA181ACC386B00A979A6 /* Cells */,
161 | B986BA361A8A65AD00E4584D /* FMMosaicCollectionViewController.h */,
162 | B986BA201A8A5F6000E4584D /* FMMosaicCollectionViewController.m */,
163 | B986BA211A8A5F6000E4584D /* main.m */,
164 | 6003F59C195388D20070C39A /* FMAppDelegate.h */,
165 | B986BA1E1A8A5F6000E4584D /* FMAppDelegate.m */,
166 | B986BA261A8A5F7D00E4584D /* Example.storyboard */,
167 | B986BA281A8A5F7D00E4584D /* LaunchScreen.xib */,
168 | 6003F5A8195388D20070C39A /* Images.xcassets */,
169 | 6003F594195388D20070C39A /* Supporting Files */,
170 | );
171 | path = FMMosaicLayout;
172 | sourceTree = "";
173 | };
174 | 6003F594195388D20070C39A /* Supporting Files */ = {
175 | isa = PBXGroup;
176 | children = (
177 | 6003F595195388D20070C39A /* FMMosaicLayout-Info.plist */,
178 | 6003F596195388D20070C39A /* InfoPlist.strings */,
179 | 6003F599195388D20070C39A /* main.m */,
180 | 6003F59B195388D20070C39A /* FMMosaicLayout-Prefix.pch */,
181 | );
182 | name = "Supporting Files";
183 | sourceTree = "";
184 | };
185 | 6003F5B5195388D20070C39A /* Tests */ = {
186 | isa = PBXGroup;
187 | children = (
188 | 6003F5BB195388D20070C39A /* Tests.m */,
189 | 6003F5B6195388D20070C39A /* Supporting Files */,
190 | );
191 | path = Tests;
192 | sourceTree = "";
193 | };
194 | 6003F5B6195388D20070C39A /* Supporting Files */ = {
195 | isa = PBXGroup;
196 | children = (
197 | 6003F5B7195388D20070C39A /* Tests-Info.plist */,
198 | 6003F5B8195388D20070C39A /* InfoPlist.strings */,
199 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
200 | );
201 | name = "Supporting Files";
202 | sourceTree = "";
203 | };
204 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
205 | isa = PBXGroup;
206 | children = (
207 | 0E432239394A4D76C39CDD75 /* FMMosaicLayout.podspec */,
208 | 18DE6644CFE566A04570A623 /* README.md */,
209 | 7CBBF3E3E5CC0B3DEF0EB910 /* LICENSE */,
210 | );
211 | name = "Podspec Metadata";
212 | sourceTree = "";
213 | };
214 | B952EA181ACC386B00A979A6 /* Cells */ = {
215 | isa = PBXGroup;
216 | children = (
217 | B986BA351A8A65AD00E4584D /* FMMosaicCellView.h */,
218 | B986BA1F1A8A5F6000E4584D /* FMMosaicCellView.m */,
219 | B960978F1AD433FE00EBD79A /* Header */,
220 | B960978E1AD433F600EBD79A /* Footer */,
221 | );
222 | name = Cells;
223 | sourceTree = "";
224 | };
225 | B960978E1AD433F600EBD79A /* Footer */ = {
226 | isa = PBXGroup;
227 | children = (
228 | B952EA0E1ACC380700A979A6 /* FMFooterView.h */,
229 | B952EA0F1ACC380700A979A6 /* FMFooterView.m */,
230 | B96097901AD4342D00EBD79A /* FMFooterView.xib */,
231 | );
232 | name = Footer;
233 | sourceTree = "";
234 | };
235 | B960978F1AD433FE00EBD79A /* Header */ = {
236 | isa = PBXGroup;
237 | children = (
238 | B952EA131ACC382600A979A6 /* FMHeaderView.h */,
239 | B952EA141ACC382600A979A6 /* FMHeaderView.m */,
240 | B96097911AD4342D00EBD79A /* FMHeaderView.xib */,
241 | );
242 | name = Header;
243 | sourceTree = "";
244 | };
245 | /* End PBXGroup section */
246 |
247 | /* Begin PBXNativeTarget section */
248 | 6003F589195388D20070C39A /* FMMosaicLayout */ = {
249 | isa = PBXNativeTarget;
250 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FMMosaicLayout" */;
251 | buildPhases = (
252 | 2A55F23405B1A758B2AB5B0E /* Check Pods Manifest.lock */,
253 | 6003F586195388D20070C39A /* Sources */,
254 | 6003F587195388D20070C39A /* Frameworks */,
255 | 6003F588195388D20070C39A /* Resources */,
256 | E99A6DF8EE0F2180DCE32AAA /* Copy Pods Resources */,
257 | );
258 | buildRules = (
259 | );
260 | dependencies = (
261 | );
262 | name = FMMosaicLayout;
263 | productName = FMMosaicLayout;
264 | productReference = 6003F58A195388D20070C39A /* FMMosaicLayout.app */;
265 | productType = "com.apple.product-type.application";
266 | };
267 | 6003F5AD195388D20070C39A /* Tests */ = {
268 | isa = PBXNativeTarget;
269 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */;
270 | buildPhases = (
271 | 7CCD0FB2E453FCB8191D6D11 /* Check Pods Manifest.lock */,
272 | 6003F5AA195388D20070C39A /* Sources */,
273 | 6003F5AB195388D20070C39A /* Frameworks */,
274 | 6003F5AC195388D20070C39A /* Resources */,
275 | 815135504CA12D6B2AF5212F /* Copy Pods Resources */,
276 | );
277 | buildRules = (
278 | );
279 | dependencies = (
280 | 6003F5B4195388D20070C39A /* PBXTargetDependency */,
281 | );
282 | name = Tests;
283 | productName = FMMosaicLayoutTests;
284 | productReference = 6003F5AE195388D20070C39A /* Tests.xctest */;
285 | productType = "com.apple.product-type.bundle.unit-test";
286 | };
287 | /* End PBXNativeTarget section */
288 |
289 | /* Begin PBXProject section */
290 | 6003F582195388D10070C39A /* Project object */ = {
291 | isa = PBXProject;
292 | attributes = {
293 | CLASSPREFIX = FM;
294 | LastUpgradeCheck = 0510;
295 | ORGANIZATIONNAME = JVillella;
296 | TargetAttributes = {
297 | 6003F5AD195388D20070C39A = {
298 | TestTargetID = 6003F589195388D20070C39A;
299 | };
300 | };
301 | };
302 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "FMMosaicLayout" */;
303 | compatibilityVersion = "Xcode 3.2";
304 | developmentRegion = English;
305 | hasScannedForEncodings = 0;
306 | knownRegions = (
307 | en,
308 | Base,
309 | );
310 | mainGroup = 6003F581195388D10070C39A;
311 | productRefGroup = 6003F58B195388D20070C39A /* Products */;
312 | projectDirPath = "";
313 | projectRoot = "";
314 | targets = (
315 | 6003F589195388D20070C39A /* FMMosaicLayout */,
316 | 6003F5AD195388D20070C39A /* Tests */,
317 | );
318 | };
319 | /* End PBXProject section */
320 |
321 | /* Begin PBXResourcesBuildPhase section */
322 | 6003F588195388D20070C39A /* Resources */ = {
323 | isa = PBXResourcesBuildPhase;
324 | buildActionMask = 2147483647;
325 | files = (
326 | B986BA2B1A8A5F7D00E4584D /* LaunchScreen.xib in Resources */,
327 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
328 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
329 | B96097921AD4342D00EBD79A /* FMFooterView.xib in Resources */,
330 | B986BA2A1A8A5F7D00E4584D /* Example.storyboard in Resources */,
331 | B96097931AD4342D00EBD79A /* FMHeaderView.xib in Resources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | 6003F5AC195388D20070C39A /* Resources */ = {
336 | isa = PBXResourcesBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | /* End PBXResourcesBuildPhase section */
344 |
345 | /* Begin PBXShellScriptBuildPhase section */
346 | 2A55F23405B1A758B2AB5B0E /* Check Pods Manifest.lock */ = {
347 | isa = PBXShellScriptBuildPhase;
348 | buildActionMask = 2147483647;
349 | files = (
350 | );
351 | inputPaths = (
352 | );
353 | name = "Check Pods Manifest.lock";
354 | outputPaths = (
355 | );
356 | runOnlyForDeploymentPostprocessing = 0;
357 | shellPath = /bin/sh;
358 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
359 | showEnvVarsInLog = 0;
360 | };
361 | 7CCD0FB2E453FCB8191D6D11 /* Check Pods Manifest.lock */ = {
362 | isa = PBXShellScriptBuildPhase;
363 | buildActionMask = 2147483647;
364 | files = (
365 | );
366 | inputPaths = (
367 | );
368 | name = "Check Pods Manifest.lock";
369 | outputPaths = (
370 | );
371 | runOnlyForDeploymentPostprocessing = 0;
372 | shellPath = /bin/sh;
373 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
374 | showEnvVarsInLog = 0;
375 | };
376 | 815135504CA12D6B2AF5212F /* Copy Pods Resources */ = {
377 | isa = PBXShellScriptBuildPhase;
378 | buildActionMask = 2147483647;
379 | files = (
380 | );
381 | inputPaths = (
382 | );
383 | name = "Copy Pods Resources";
384 | outputPaths = (
385 | );
386 | runOnlyForDeploymentPostprocessing = 0;
387 | shellPath = /bin/sh;
388 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n";
389 | showEnvVarsInLog = 0;
390 | };
391 | E99A6DF8EE0F2180DCE32AAA /* Copy Pods Resources */ = {
392 | isa = PBXShellScriptBuildPhase;
393 | buildActionMask = 2147483647;
394 | files = (
395 | );
396 | inputPaths = (
397 | );
398 | name = "Copy Pods Resources";
399 | outputPaths = (
400 | );
401 | runOnlyForDeploymentPostprocessing = 0;
402 | shellPath = /bin/sh;
403 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FMMosaicLayout/Pods-FMMosaicLayout-resources.sh\"\n";
404 | showEnvVarsInLog = 0;
405 | };
406 | /* End PBXShellScriptBuildPhase section */
407 |
408 | /* Begin PBXSourcesBuildPhase section */
409 | 6003F586195388D20070C39A /* Sources */ = {
410 | isa = PBXSourcesBuildPhase;
411 | buildActionMask = 2147483647;
412 | files = (
413 | B986BA221A8A5F6000E4584D /* FMAppDelegate.m in Sources */,
414 | B952EA111ACC380700A979A6 /* FMFooterView.m in Sources */,
415 | B986BA231A8A5F6000E4584D /* FMMosaicCellView.m in Sources */,
416 | B986BA241A8A5F6000E4584D /* FMMosaicCollectionViewController.m in Sources */,
417 | B952EA161ACC382600A979A6 /* FMHeaderView.m in Sources */,
418 | B986BA251A8A5F6000E4584D /* main.m in Sources */,
419 | );
420 | runOnlyForDeploymentPostprocessing = 0;
421 | };
422 | 6003F5AA195388D20070C39A /* Sources */ = {
423 | isa = PBXSourcesBuildPhase;
424 | buildActionMask = 2147483647;
425 | files = (
426 | 6003F5BC195388D20070C39A /* Tests.m in Sources */,
427 | );
428 | runOnlyForDeploymentPostprocessing = 0;
429 | };
430 | /* End PBXSourcesBuildPhase section */
431 |
432 | /* Begin PBXTargetDependency section */
433 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
434 | isa = PBXTargetDependency;
435 | target = 6003F589195388D20070C39A /* FMMosaicLayout */;
436 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
437 | };
438 | /* End PBXTargetDependency section */
439 |
440 | /* Begin PBXVariantGroup section */
441 | 6003F596195388D20070C39A /* InfoPlist.strings */ = {
442 | isa = PBXVariantGroup;
443 | children = (
444 | 6003F597195388D20070C39A /* en */,
445 | );
446 | name = InfoPlist.strings;
447 | sourceTree = "";
448 | };
449 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
450 | isa = PBXVariantGroup;
451 | children = (
452 | 6003F5B9195388D20070C39A /* en */,
453 | );
454 | name = InfoPlist.strings;
455 | sourceTree = "";
456 | };
457 | B986BA261A8A5F7D00E4584D /* Example.storyboard */ = {
458 | isa = PBXVariantGroup;
459 | children = (
460 | B986BA271A8A5F7D00E4584D /* Base */,
461 | );
462 | name = Example.storyboard;
463 | sourceTree = "";
464 | };
465 | B986BA281A8A5F7D00E4584D /* LaunchScreen.xib */ = {
466 | isa = PBXVariantGroup;
467 | children = (
468 | B986BA291A8A5F7D00E4584D /* Base */,
469 | );
470 | name = LaunchScreen.xib;
471 | sourceTree = "";
472 | };
473 | /* End PBXVariantGroup section */
474 |
475 | /* Begin XCBuildConfiguration section */
476 | 6003F5BD195388D20070C39A /* Debug */ = {
477 | isa = XCBuildConfiguration;
478 | buildSettings = {
479 | ALWAYS_SEARCH_USER_PATHS = NO;
480 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
481 | CLANG_CXX_LIBRARY = "libc++";
482 | CLANG_ENABLE_MODULES = YES;
483 | CLANG_ENABLE_OBJC_ARC = YES;
484 | CLANG_WARN_BOOL_CONVERSION = YES;
485 | CLANG_WARN_CONSTANT_CONVERSION = YES;
486 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
487 | CLANG_WARN_EMPTY_BODY = YES;
488 | CLANG_WARN_ENUM_CONVERSION = YES;
489 | CLANG_WARN_INT_CONVERSION = YES;
490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
491 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
492 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
493 | COPY_PHASE_STRIP = NO;
494 | GCC_C_LANGUAGE_STANDARD = gnu99;
495 | GCC_DYNAMIC_NO_PIC = NO;
496 | GCC_OPTIMIZATION_LEVEL = 0;
497 | GCC_PREPROCESSOR_DEFINITIONS = (
498 | "DEBUG=1",
499 | "$(inherited)",
500 | );
501 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
502 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
503 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
504 | GCC_WARN_UNDECLARED_SELECTOR = YES;
505 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
506 | GCC_WARN_UNUSED_FUNCTION = YES;
507 | GCC_WARN_UNUSED_VARIABLE = YES;
508 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
509 | ONLY_ACTIVE_ARCH = YES;
510 | SDKROOT = iphoneos;
511 | TARGETED_DEVICE_FAMILY = "1,2";
512 | };
513 | name = Debug;
514 | };
515 | 6003F5BE195388D20070C39A /* Release */ = {
516 | isa = XCBuildConfiguration;
517 | buildSettings = {
518 | ALWAYS_SEARCH_USER_PATHS = NO;
519 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
520 | CLANG_CXX_LIBRARY = "libc++";
521 | CLANG_ENABLE_MODULES = YES;
522 | CLANG_ENABLE_OBJC_ARC = YES;
523 | CLANG_WARN_BOOL_CONVERSION = YES;
524 | CLANG_WARN_CONSTANT_CONVERSION = YES;
525 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
526 | CLANG_WARN_EMPTY_BODY = YES;
527 | CLANG_WARN_ENUM_CONVERSION = YES;
528 | CLANG_WARN_INT_CONVERSION = YES;
529 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
530 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
531 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
532 | COPY_PHASE_STRIP = YES;
533 | ENABLE_NS_ASSERTIONS = NO;
534 | GCC_C_LANGUAGE_STANDARD = gnu99;
535 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
536 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
537 | GCC_WARN_UNDECLARED_SELECTOR = YES;
538 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
539 | GCC_WARN_UNUSED_FUNCTION = YES;
540 | GCC_WARN_UNUSED_VARIABLE = YES;
541 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
542 | SDKROOT = iphoneos;
543 | TARGETED_DEVICE_FAMILY = "1,2";
544 | VALIDATE_PRODUCT = YES;
545 | };
546 | name = Release;
547 | };
548 | 6003F5C0195388D20070C39A /* Debug */ = {
549 | isa = XCBuildConfiguration;
550 | baseConfigurationReference = 7605C3CD52D024CD64BFE751 /* Pods-FMMosaicLayout.debug.xcconfig */;
551 | buildSettings = {
552 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
553 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
554 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
555 | GCC_PREFIX_HEADER = "FMMosaicLayout/FMMosaicLayout-Prefix.pch";
556 | INFOPLIST_FILE = "FMMosaicLayout/FMMosaicLayout-Info.plist";
557 | IPHONEOS_DEPLOYMENT_TARGET = 8.2;
558 | PRODUCT_NAME = "$(TARGET_NAME)";
559 | WRAPPER_EXTENSION = app;
560 | };
561 | name = Debug;
562 | };
563 | 6003F5C1195388D20070C39A /* Release */ = {
564 | isa = XCBuildConfiguration;
565 | baseConfigurationReference = 564285136DBFDA264B2EA590 /* Pods-FMMosaicLayout.release.xcconfig */;
566 | buildSettings = {
567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
568 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
569 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
570 | GCC_PREFIX_HEADER = "FMMosaicLayout/FMMosaicLayout-Prefix.pch";
571 | INFOPLIST_FILE = "FMMosaicLayout/FMMosaicLayout-Info.plist";
572 | IPHONEOS_DEPLOYMENT_TARGET = 8.2;
573 | PRODUCT_NAME = "$(TARGET_NAME)";
574 | WRAPPER_EXTENSION = app;
575 | };
576 | name = Release;
577 | };
578 | 6003F5C3195388D20070C39A /* Debug */ = {
579 | isa = XCBuildConfiguration;
580 | baseConfigurationReference = 57344976FD9A706AF9A5C0F6 /* Pods-Tests.debug.xcconfig */;
581 | buildSettings = {
582 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FMMosaicLayout.app/FMMosaicLayout";
583 | FRAMEWORK_SEARCH_PATHS = (
584 | "$(SDKROOT)/Developer/Library/Frameworks",
585 | "$(inherited)",
586 | "$(DEVELOPER_FRAMEWORKS_DIR)",
587 | );
588 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
589 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
590 | GCC_PREPROCESSOR_DEFINITIONS = (
591 | "DEBUG=1",
592 | "$(inherited)",
593 | );
594 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
595 | PRODUCT_NAME = "$(TARGET_NAME)";
596 | TEST_HOST = "$(BUNDLE_LOADER)";
597 | WRAPPER_EXTENSION = xctest;
598 | };
599 | name = Debug;
600 | };
601 | 6003F5C4195388D20070C39A /* Release */ = {
602 | isa = XCBuildConfiguration;
603 | baseConfigurationReference = 271B5DC9EE27D3AF67E31CC1 /* Pods-Tests.release.xcconfig */;
604 | buildSettings = {
605 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/FMMosaicLayout.app/FMMosaicLayout";
606 | FRAMEWORK_SEARCH_PATHS = (
607 | "$(SDKROOT)/Developer/Library/Frameworks",
608 | "$(inherited)",
609 | "$(DEVELOPER_FRAMEWORKS_DIR)",
610 | );
611 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
612 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
613 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
614 | PRODUCT_NAME = "$(TARGET_NAME)";
615 | TEST_HOST = "$(BUNDLE_LOADER)";
616 | WRAPPER_EXTENSION = xctest;
617 | };
618 | name = Release;
619 | };
620 | /* End XCBuildConfiguration section */
621 |
622 | /* Begin XCConfigurationList section */
623 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "FMMosaicLayout" */ = {
624 | isa = XCConfigurationList;
625 | buildConfigurations = (
626 | 6003F5BD195388D20070C39A /* Debug */,
627 | 6003F5BE195388D20070C39A /* Release */,
628 | );
629 | defaultConfigurationIsVisible = 0;
630 | defaultConfigurationName = Release;
631 | };
632 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "FMMosaicLayout" */ = {
633 | isa = XCConfigurationList;
634 | buildConfigurations = (
635 | 6003F5C0195388D20070C39A /* Debug */,
636 | 6003F5C1195388D20070C39A /* Release */,
637 | );
638 | defaultConfigurationIsVisible = 0;
639 | defaultConfigurationName = Release;
640 | };
641 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */ = {
642 | isa = XCConfigurationList;
643 | buildConfigurations = (
644 | 6003F5C3195388D20070C39A /* Debug */,
645 | 6003F5C4195388D20070C39A /* Release */,
646 | );
647 | defaultConfigurationIsVisible = 0;
648 | defaultConfigurationName = Release;
649 | };
650 | /* End XCConfigurationList section */
651 | };
652 | rootObject = 6003F582195388D10070C39A /* Project object */;
653 | }
654 |
--------------------------------------------------------------------------------