diff --git a/CardsStack.xcodeproj/project.pbxproj b/CardsStack.xcodeproj/project.pbxproj index c977de4..2bce94f 100644 --- a/CardsStack.xcodeproj/project.pbxproj +++ b/CardsStack.xcodeproj/project.pbxproj @@ -351,6 +351,7 @@ SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -371,6 +372,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/CardsStack/CardLayout.swift b/CardsStack/CardLayout.swift index 0bb508d..cb14b63 100644 --- a/CardsStack/CardLayout.swift +++ b/CardsStack/CardLayout.swift @@ -2,14 +2,14 @@ // CardLayout.swift // DynamicStackOfCards // -// Created by housing on 9/16/16. +// Created by Pritesh Nandgaonkar on 9/16/16. // Copyright © 2016 pritesh. All rights reserved. // import Foundation import UIKit -protocol CardLayoutDelegate { +internal protocol CardLayoutDelegate { var fractionToMove: Float { get } var cardState: CardState { get } var configuration: Configuration { get } @@ -22,6 +22,14 @@ class CardLayout: UICollectionViewLayout { var cachedAttributes = [UICollectionViewLayoutAttributes]() + override init() { + super.init() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override var collectionViewContentSize: CGSize { let collection = collectionView! let width = collection.bounds.size.width diff --git a/CardsStack/CardStack.swift b/CardsStack/CardStack.swift index a56f3a6..6c5fac5 100644 --- a/CardsStack/CardStack.swift +++ b/CardsStack/CardStack.swift @@ -2,29 +2,57 @@ // CardStack.swift // DynamicStackOfCards // -// Created by housing on 9/24/16. +// Created by Pritesh Nandgaonkar on 9/24/16. // Copyright © 2016 pritesh. All rights reserved. // import Foundation import UIKit -@objc public enum CardsPosition: Int { - case Collapsed - case Expanded -} - +/// Struct for the UI information related to cards. public struct Configuration { + + /// Offset(distance between the top of the consecutive cards) between the cards while the cards are in collapsed state public let cardOffset: Float + + /// Height of the collection view when the cards are in collapsed state public let collapsedHeight:Float + + /// Height of the collection view when the cards are in expanded state public let expandedHeight:Float + + /// Height of the cards public let cardHeight: Float + + /// The minimum threshold required for the cards to be dragged down when the cards are in expanded state public let downwardThreshold: Float + + /// The minimum threshold required for the cards to be dragged up when the cards are in collapsed state public let upwardThreshold: Float + + /// Vertical Spacing between the cards while the cards are in expanded state public let verticalSpacing: Float + + /// Leading space for the cards public let leftSpacing: Float + + /// Trailing space for the cards public let rightSpacing: Float + + /// init + /// + /// - parameter cardOffset: Offset(distance between the top of the consecutive cards) between the cards while the cards are in collapsed state + /// - parameter collapsedHeight: Height of the collection view when the cards are in collapsed state + /// - parameter expandedHeight: Height of the collection view when the cards are in expanded state + /// - parameter cardHeight: Height of the cards + /// - parameter downwardThreshold: The minimum threshold required for the cards to be dragged down when the cards are in expanded state. Its an optional field. Default value is 20 + /// - parameter upwardThreshold: The minimum threshold required for the cards to be dragged up when the cards are in collapsed state. Its an optional field. Default value is 20 + /// - parameter leftSpacing: Leading space for the cards. Its not a required field, default value is 8 + /// - parameter rightSpacing: Trailing space for the cards. Optional field, default value is 8 + /// - parameter verticalSpacing: Leading space for the cards. Optional field, default value is 8 + /// + /// - returns: Configuration public init(cardOffset: Float, collapsedHeight: Float, expandedHeight: Float, cardHeight: Float, downwardThreshold: Float = 20, upwardThreshold: Float = 20, leftSpacing: Float = 8.0, rightSpacing: Float = 8.0, verticalSpacing: Float = 8.0) { self.cardOffset = cardOffset self.collapsedHeight = collapsedHeight @@ -38,6 +66,16 @@ public struct Configuration { } } +/// Enum for decribing the state of the cards +@objc public enum CardsPosition: Int { + /// Case when the cards are collapsed + case Collapsed + + /// Case when the cards are expanded + case Expanded +} + +/// Delegate to get hooks to interaction over cards @objc public protocol CardsManagerDelegate { @objc optional func cardsPositionChangedTo(position: CardsPosition) @@ -46,6 +84,7 @@ public struct Configuration { @objc optional func cardsCollectionView(_ cardsCollectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) } +/// Class for initialising stack of cards public class CardStack { public weak var delegate: CardsManagerDelegate? = nil { @@ -53,16 +92,28 @@ public class CardStack { cardsManager.delegate = delegate } } - private var cardsManager = CardsManager() + internal var cardsManager = CardsManager() internal(set) var position: CardsPosition + /// init + /// uses config = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20) in + /// init(cardsState: .Collapsed, configuration: config, collectionView: nil, collectionViewHeight: nil) + /// - returns: CardStack public convenience init() { let configuration = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20) self.init(cardsState: .Collapsed, configuration: configuration, collectionView: nil, collectionViewHeight: nil) } + /// init + /// + /// - parameter cardsState: Initial state of the cards + /// - parameter configuration: Instance of the Configuration, which holds the UI related information + /// - parameter collectionView: UICollectionView + /// - parameter collectionViewHeight: NSLayoutConstraint, height constraint of the collectionview + /// + /// - returns: CardStack public init(cardsState: CardsPosition, configuration: Configuration, collectionView: UICollectionView?, collectionViewHeight: NSLayoutConstraint?) { position = cardsState @@ -70,6 +121,9 @@ public class CardStack { cardsManager.cardsDelegate = self } + /// changeCardsPosition(to position: CardsPosition) + /// This function can be called on CardStack to change the state of cardsStack. It can be used to programmatically change the states of the cards stack + /// - parameter position: CardsPosition public func changeCardsPosition(to position: CardsPosition) { cardsManager.updateView(with: position) } diff --git a/CardsStack/CardsManager.swift b/CardsStack/CardsManager.swift index b8ac9b6..d24faaf 100644 --- a/CardsStack/CardsManager.swift +++ b/CardsStack/CardsManager.swift @@ -2,7 +2,7 @@ // CardsManager.swift // DynamicStackOfCards // -// Created by housing on 9/24/16. +// Created by Pritesh Nandgaonkar on 9/24/16. // Copyright © 2016 pritesh. All rights reserved. // @@ -15,7 +15,7 @@ internal enum CardState { case Collapsed } -internal class CardsManager: NSObject, CardLayoutDelegate { +class CardsManager: NSObject, CardLayoutDelegate { var fractionToMove:Float = 0 var cardState: CardState { @@ -89,10 +89,13 @@ internal class CardsManager: NSObject, CardLayoutDelegate { guard let cardsView = self.collectionView else { return } + let cardLayout = CardLayout() + cardLayout.delegate = self + cardsView.collectionViewLayout = cardLayout + cardsView.bounces = true + cardsView.alwaysBounceVertical = true cardsView.delegate = self - if let cardLayout = cardsView.collectionViewLayout as? CardLayout { - cardLayout.delegate = self - } + panGesture = UIPanGestureRecognizer(target: self, action:#selector(self.pannedCard)) tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tappedCard)) cardsView.addGestureRecognizer(panGesture) @@ -109,6 +112,7 @@ internal class CardsManager: NSObject, CardLayoutDelegate { } func pannedCard(panGesture: UIPanGestureRecognizer) { + guard let collectionView = self.collectionView else { return } @@ -172,7 +176,6 @@ internal class CardsManager: NSObject, CardLayoutDelegate { }, completion: { (finished) in self.triggerStateCallBack() }) - default: break } @@ -222,13 +225,14 @@ extension CardsManager: UICollectionViewDelegate { public func scrollViewDidScroll(_ scrollView: UIScrollView) { - if scrollView.contentOffset.y < -10 { + if scrollView.contentOffset.y < 0 { panGesture.isEnabled = true scrollView.isScrollEnabled = false } } public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + delegate?.cardsCollectionView?(collectionView, didSelectItemAt: indexPath) } diff --git a/CardsStack/CardsStack.h b/CardsStack/CardsStack.h index b44e3d2..8c73bf4 100644 --- a/CardsStack/CardsStack.h +++ b/CardsStack/CardsStack.h @@ -2,7 +2,7 @@ // CardsStack.h // CardsStack // -// Created by housing on 9/24/16. +// Created by Pritesh Nandgaonkar on 9/24/16. // Copyright © 2016 Pritesh. All rights reserved. // @@ -16,4 +16,3 @@ FOUNDATION_EXPORT const unsigned char CardsStackVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import - diff --git a/CardsStackTests/CardsStackTests.swift b/CardsStackTests/CardsStackTests.swift index 1fb01f9..6bb19b0 100644 --- a/CardsStackTests/CardsStackTests.swift +++ b/CardsStackTests/CardsStackTests.swift @@ -2,7 +2,7 @@ // CardsStackTests.swift // CardsStackTests // -// Created by housing on 9/24/16. +// Created by Pritesh Nandgaonkar on 9/24/16. // Copyright © 2016 Pritesh. All rights reserved. // diff --git a/README.md b/README.md index ba37c4f..07ab72a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# CardStack +# CardStack [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -CardStack converts your `UICollectionView` to an awesome stack of cards + +CardStack converts your `UICollectionView` to an awesome stack of cards using custom `UICollectionViewLayout` ## What is CardStack? 💫 ✨💥⭐️ @@ -91,13 +92,13 @@ With this delegate you can get the hooks to specific events } ``` -For listening to thiscall backs add assign a delegate to `CardsStack` +For listening to this call backs assign a delegate to `CardsStack` ``` swift cardsStack.delegate = self ``` -The last two functions leads are the same as the delegate function for collection view. +The last two functions are the same as the delegate function for collection view. The first function gives the hook to the `CardStacks` position change @@ -127,7 +128,7 @@ public func changeCardsPosition(to position: CardsPosition) { You can checkout the example and play around with it to get hang of the API's ## TODO -- [ ] Carthage Support +- [x] Carthage Support - [ ] CocoaPods Support - [ ] SwiftPM Support - [ ] Watch, TvOS Targets