diff --git a/CarLensCollectionViewLayout.podspec b/CarLensCollectionViewLayout.podspec index 4eee107..31cc1e5 100644 --- a/CarLensCollectionViewLayout.podspec +++ b/CarLensCollectionViewLayout.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "CarLensCollectionViewLayout" - s.version = "1.0.0" + s.version = "1.1.0" s.summary = "An easy to use Collection View Layout for card-like animation." s.homepage = "https://github.com/netguru/CarLensCollectionViewLayout" diff --git a/CarLensCollectionViewLayout.xcodeproj/project.pbxproj b/CarLensCollectionViewLayout.xcodeproj/project.pbxproj index 1d6cc6b..d1d316a 100644 --- a/CarLensCollectionViewLayout.xcodeproj/project.pbxproj +++ b/CarLensCollectionViewLayout.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 9518383821E4F31F00BEA6EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9518382421E4F08300BEA6EB /* Assets.xcassets */; }; 9518383921E4F32800BEA6EB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9518382921E4F08300BEA6EB /* AppDelegate.swift */; }; 9518383C21E4FFCA00BEA6EB /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9518383B21E4FFCA00BEA6EB /* CollectionViewCell.swift */; }; + 9518384821E623E800BEA6EB /* CarLensCollectionViewLayoutOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9518384721E623E800BEA6EB /* CarLensCollectionViewLayoutOptions.swift */; }; 955E4FD421CBFB2800B4C3BB /* CarLensCollectionViewLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 955E4FD221CBFB2800B4C3BB /* CarLensCollectionViewLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 958D17C021D66DF00067BED6 /* CarLensCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958D17BF21D66DF00067BED6 /* CarLensCollectionViewCell.swift */; }; /* End PBXBuildFile section */ @@ -56,6 +57,7 @@ 9518382921E4F08300BEA6EB /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 9518382A21E4F08300BEA6EB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9518383B21E4FFCA00BEA6EB /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; + 9518384721E623E800BEA6EB /* CarLensCollectionViewLayoutOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarLensCollectionViewLayoutOptions.swift; sourceTree = ""; }; 955E4FCF21CBFB2800B4C3BB /* CarLensCollectionViewLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CarLensCollectionViewLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 955E4FD221CBFB2800B4C3BB /* CarLensCollectionViewLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CarLensCollectionViewLayout.h; sourceTree = ""; }; 955E4FD321CBFB2800B4C3BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -126,6 +128,7 @@ children = ( 955E4FD221CBFB2800B4C3BB /* CarLensCollectionViewLayout.h */, 9505725D21D4D8FB009EA422 /* CarLensCollectionViewLayout.swift */, + 9518384721E623E800BEA6EB /* CarLensCollectionViewLayoutOptions.swift */, 958D17BF21D66DF00067BED6 /* CarLensCollectionViewCell.swift */, 9505725F21D4D922009EA422 /* CarLensLayoutAttributes.swift */, 955E4FD321CBFB2800B4C3BB /* Info.plist */, @@ -256,6 +259,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9518384821E623E800BEA6EB /* CarLensCollectionViewLayoutOptions.swift in Sources */, 9505725E21D4D8FB009EA422 /* CarLensCollectionViewLayout.swift in Sources */, 958D17C021D66DF00067BED6 /* CarLensCollectionViewCell.swift in Sources */, 9505726021D4D922009EA422 /* CarLensLayoutAttributes.swift in Sources */, diff --git a/CarLensCollectionViewLayout/CarLensCollectionViewCell.swift b/CarLensCollectionViewLayout/CarLensCollectionViewCell.swift index bdd86e0..c58c87b 100644 --- a/CarLensCollectionViewLayout/CarLensCollectionViewCell.swift +++ b/CarLensCollectionViewLayout/CarLensCollectionViewCell.swift @@ -19,14 +19,17 @@ open class CarLensCollectionViewCell: UICollectionViewCell { /// The bottom view of the cell. public var cardView: UIView! - private let topViewHeight: CGFloat = UIScreen.main.bounds.height > 568 ? 200 : 170 + /// The height of the top view. + public var topViewHeight: CGFloat! /// Configuration of the cell. Must be called on a start. /// /// - Parameters: /// - topView: The upper view of the cell. /// - cardView: The bottom view of the cell. - open func configure(topView: UIView, cardView: UIView) { + /// - topViewHeight: An optional parameter to specify the custom height of the top view. The default value is `170` or `200` depending on a device's size. + open func configure(topView: UIView, cardView: UIView, topViewHeight: CGFloat = UIScreen.main.bounds.height > 568 ? 200 : 170) { + self.topViewHeight = topViewHeight self.topView = topView self.cardView = cardView setupView() diff --git a/CarLensCollectionViewLayout/CarLensCollectionViewLayout.h b/CarLensCollectionViewLayout/CarLensCollectionViewLayout.h index 5bbe189..69417ff 100644 --- a/CarLensCollectionViewLayout/CarLensCollectionViewLayout.h +++ b/CarLensCollectionViewLayout/CarLensCollectionViewLayout.h @@ -7,12 +7,12 @@ #import -//! Project version number for CarlensCollectionViewLayout. -FOUNDATION_EXPORT double CarlensCollectionViewLayoutVersionNumber; +//! Project version number for CarLensCollectionViewLayout. +FOUNDATION_EXPORT double CarLensCollectionViewLayoutVersionNumber; -//! Project version string for CarlensCollectionViewLayout. -FOUNDATION_EXPORT const unsigned char CarlensCollectionViewLayoutVersionString[]; +//! Project version string for CarLensCollectionViewLayout. +FOUNDATION_EXPORT const unsigned char CarLensCollectionViewLayoutVersionString[]; -// In this header, you should import all the public headers of your framework using statements like #import +// In this header, you should import all the public headers of your framework using statements like #import diff --git a/CarLensCollectionViewLayout/CarLensCollectionViewLayout.swift b/CarLensCollectionViewLayout/CarLensCollectionViewLayout.swift index c8eb235..908cfde 100644 --- a/CarLensCollectionViewLayout/CarLensCollectionViewLayout.swift +++ b/CarLensCollectionViewLayout/CarLensCollectionViewLayout.swift @@ -11,6 +11,8 @@ public final class CarLensCollectionViewLayout: UICollectionViewFlowLayout { private var firstSetupDone = false + private let options: CarLensCollectionViewLayoutOptions + /// SeeAlso: UICollectionViewFlowLayout public override func prepare() { super.prepare() @@ -19,14 +21,31 @@ public final class CarLensCollectionViewLayout: UICollectionViewFlowLayout { firstSetupDone = true } + + /// The initialization of the CarLensCollectionViewLayout. + /// + /// - Parameters: + /// - options: An optional additional configuration of the layout. + public init(options: CarLensCollectionViewLayoutOptions = CarLensCollectionViewLayoutOptions()) { + self.options = options + super.init() + } + + public required init?(coder aDecoder: NSCoder) { + self.options = CarLensCollectionViewLayoutOptions() + super.init(coder: aDecoder) + } + private func setup() { guard let collectionView = collectionView else { return } scrollDirection = .horizontal - minimumLineSpacing = 20 - itemSize = CGSize(width: collectionView.bounds.width - 80, height: collectionView.bounds.height) - let inset = (collectionView.bounds.width - itemSize.width) / 2 - collectionView.contentInset = .init(top: 0, left: inset, bottom: 0, right: inset) - collectionView.decelerationRate = UIScrollView.DecelerationRate.fast + minimumLineSpacing = options.minimumSpacing + itemSize = options.itemSize ?? CGSize(width: collectionView.bounds.width - 60, height: collectionView.bounds.height) + let sidesInset = (collectionView.bounds.width - itemSize.width) / 2 + let topAndBottomInset = (collectionView.bounds.height - itemSize.height) / 2 + collectionView.contentInset = .init(top: topAndBottomInset, left: sidesInset, bottom: topAndBottomInset, right: sidesInset) + collectionView.decelerationRate = options.decelerationRate + collectionView.showsHorizontalScrollIndicator = options.shouldShowScrollIndicator } /// SeeAlso: UICollectionViewFlowLayout diff --git a/CarLensCollectionViewLayout/CarLensCollectionViewLayoutOptions.swift b/CarLensCollectionViewLayout/CarLensCollectionViewLayoutOptions.swift new file mode 100644 index 0000000..2385e98 --- /dev/null +++ b/CarLensCollectionViewLayout/CarLensCollectionViewLayoutOptions.swift @@ -0,0 +1,40 @@ +// +// CarLensCollectionViewLayoutOptions.swift +// CarLensCollectionViewLayout +// +// Copyright © 2019 Netguru. All rights reserved. +// + +import UIKit + +/// The optional configuration of CarLensCollectionViewLayout. Use this if you need to customize `CarLensCollectionViewLayout`. +public struct CarLensCollectionViewLayoutOptions { + + /// A minimum spacing between cells. + let minimumSpacing: CGFloat + + /// A deceleration for a scroll view. + let decelerationRate: UIScrollView.DecelerationRate + + /// A value indicating whether collection view should have a scroll indicator. + let shouldShowScrollIndicator: Bool + + /// The size to use for cells. + let itemSize: CGSize? + + /// The initialization of the optional layout configuration. + /// You can initialize it with any of the parameters available. Others will be configured automatically. + /// + /// - Parameters: + /// - minimumSpacing: A minimum spacing between cells. The default value is `20`. + /// - decelerationRate: A deceleration for a scroll view. The default value is `.fast`. + /// - shouldShowScrollIndicator: A value indicating whether collection view should have a scroll indicator. The default value is `false`. + /// - itemSize: The size to use for cells. The default height is equal to a collection view height. The width is equal to the `collection view width - 60`. + public init(minimumSpacing: CGFloat = 20, decelerationRate: UIScrollView.DecelerationRate = UIScrollView.DecelerationRate.fast, shouldShowScrollIndicator: Bool = false, itemSize: CGSize? = nil) { + self.minimumSpacing = minimumSpacing + self.decelerationRate = decelerationRate + self.shouldShowScrollIndicator = shouldShowScrollIndicator + self.itemSize = itemSize + } + +} diff --git a/CarLensCollectionViewLayout/Info.plist b/CarLensCollectionViewLayout/Info.plist index e1fe4cf..a4cf4c4 100644 --- a/CarLensCollectionViewLayout/Info.plist +++ b/CarLensCollectionViewLayout/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.1.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/README.md b/README.md index 4abc13d..fe6162d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ![](https://img.shields.io/badge/carthage-compatible-green.svg) ![](https://app.bitrise.io/app/23a07b63b3f55f97/status.svg?token=Rt_2gKUavbR8LQ7PVuTbYg&branch=master) -An easy to use Collection View Layout for card-like animation 🎉 +An easy-to-use Collection View Layout for card-like animation 🎉

@@ -20,9 +20,11 @@ An easy to use Collection View Layout for card-like animation 🎉 ## Usage +### Basic Usage + The two main steps are needed for the configuration of *CarLensCollectionViewLayout*: -### Step 1 +#### Step 1 Assign `CarLensCollectionViewLayout` to yours collection view layout: ```swift collectionView.collectionViewLayout = CarLensCollectionViewLayout() @@ -32,7 +34,7 @@ or initialize your collection view with `CarLensCollectionViewLayout`: UICollectionView(frame: .zero, collectionViewLayout: CarLensCollectionViewLayout()) ``` -### Step 2 +#### Step 2 Subsclass `CarLensCollectionViewCell` and call `configure(topView: UIView, cardView: UIView)` right on the start! ```swift class CollectionViewCell: CarLensCollectionViewCell { @@ -42,7 +44,41 @@ class CollectionViewCell: CarLensCollectionViewCell { } } ``` -The sample implementation is available in [Demo](CarLensCollectionViewDemo) project. +The sample implementation is available in [Demo](CarLensCollectionViewLayoutDemo) project. + +### Customization + +#### Layout +You can also initialize `CarLensCollectionViewLayout` with a `CarLensCollectionViewLayoutOptions` object by passing any of the parameters available. Others will be configured automatically. + +**Parameters:** + +`minimumSpacing` - A minimum spacing between cells. + +`decelerationRate` - A deceleration for a scroll view. + +`shouldShowScrollIndicator` - A value indicating whether collection view should have a scroll indicator. + +`itemSize` - The size to use for cells. + +Example: +```swift +let options = CarLensCollectionViewLayoutOptions(minimumSpacing: 40) +collectionView.collectionViewLayout = CarLensCollectionViewLayout(options: options) +``` + +#### Cell +While subsclassing `CarLensCollectionViewCell` you can call `configure(...)` with an additional parameter `topViewHeight`. The card view height will be calculated based on this value. + +Example: +```swift +class CollectionViewCell: CarLensCollectionViewCell { + override init(frame: CGRect) { + super.init(frame: frame) + configure(topView: upperView, cardView: bottomView, topViewHeight: 300) + } +} +``` ## Installation @@ -52,7 +88,7 @@ If you're using [CocoaPods](http://cocoapods.org), add the following dependency ```none use_frameworks! -pod 'CarLensCollectionViewLayout', '~> 1.0.0' +pod 'CarLensCollectionViewLayout', '~> 1.1.0' ``` ### Carthage @@ -60,7 +96,7 @@ pod 'CarLensCollectionViewLayout', '~> 1.0.0' If you're using [Carthage](https://github.com/Carthage/Carthage), add the following dependency to your `Cartfile`: ```none -github "netguru/CarLensCollectionViewLayout" ~> 1.0.0 +github "netguru/CarLensCollectionViewLayout" ~> 1.1.0 ``` ## About