diff --git a/Example/WOWCardStackView.xcodeproj/project.pbxproj b/Example/WOWCardStackView.xcodeproj/project.pbxproj index 0d8f2f2..394e201 100644 --- a/Example/WOWCardStackView.xcodeproj/project.pbxproj +++ b/Example/WOWCardStackView.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 386177201E7BBF68006F4F5E /* DetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3861771F1E7BBF68006F4F5E /* DetailsViewController.swift */; }; + 386177221E7BC2DD006F4F5E /* placeholder.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 386177211E7BC2DD006F4F5E /* placeholder.jpg */; }; 38F5CE7A1E7B881700A7FCA0 /* MyCard.xib in Resources */ = {isa = PBXBuildFile; fileRef = 38F5CE791E7B881700A7FCA0 /* MyCard.xib */; }; 38F5CE7C1E7B8A1600A7FCA0 /* MyCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38F5CE7B1E7B8A1600A7FCA0 /* MyCard.swift */; }; 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; @@ -34,6 +36,8 @@ 0C60282BA410B7570717C313 /* Pods-WOWCardStackView_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WOWCardStackView_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WOWCardStackView_Tests/Pods-WOWCardStackView_Tests.debug.xcconfig"; sourceTree = ""; }; 22BB6C624B682C38943B9C46 /* Pods_WOWCardStackView_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WOWCardStackView_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30091B23E72D1AB9E49886BF /* Pods-WOWCardStackView_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WOWCardStackView_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-WOWCardStackView_Example/Pods-WOWCardStackView_Example.release.xcconfig"; sourceTree = ""; }; + 3861771F1E7BBF68006F4F5E /* DetailsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailsViewController.swift; sourceTree = ""; }; + 386177211E7BC2DD006F4F5E /* placeholder.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = placeholder.jpg; sourceTree = ""; }; 38F5CE791E7B881700A7FCA0 /* MyCard.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyCard.xib; sourceTree = ""; }; 38F5CE7B1E7B8A1600A7FCA0 /* MyCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyCard.swift; sourceTree = ""; }; 5D57B462CADD95BAA877731F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; @@ -108,6 +112,7 @@ 607FACD21AFB9204008FA782 /* Example for WOWCardStackView */ = { isa = PBXGroup; children = ( + 386177211E7BC2DD006F4F5E /* placeholder.jpg */, 38F5CE7B1E7B8A1600A7FCA0 /* MyCard.swift */, 38F5CE791E7B881700A7FCA0 /* MyCard.xib */, 607FACD51AFB9204008FA782 /* AppDelegate.swift */, @@ -116,6 +121,7 @@ 607FACDC1AFB9204008FA782 /* Images.xcassets */, 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 607FACD31AFB9204008FA782 /* Supporting Files */, + 3861771F1E7BBF68006F4F5E /* DetailsViewController.swift */, ); name = "Example for WOWCardStackView"; path = WOWCardStackView; @@ -257,6 +263,7 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, + 386177221E7BC2DD006F4F5E /* placeholder.jpg in Resources */, 38F5CE7A1E7B881700A7FCA0 /* MyCard.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -371,6 +378,7 @@ 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 38F5CE7C1E7B8A1600A7FCA0 /* MyCard.swift in Sources */, + 386177201E7BBF68006F4F5E /* DetailsViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/WOWCardStackView/Base.lproj/Main.storyboard b/Example/WOWCardStackView/Base.lproj/Main.storyboard index e64a567..4a2d4c4 100644 --- a/Example/WOWCardStackView/Base.lproj/Main.storyboard +++ b/Example/WOWCardStackView/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -23,10 +23,10 @@ - + - + @@ -45,12 +45,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/WOWCardStackView/DetailsViewController.swift b/Example/WOWCardStackView/DetailsViewController.swift new file mode 100644 index 0000000..6cd90e5 --- /dev/null +++ b/Example/WOWCardStackView/DetailsViewController.swift @@ -0,0 +1,45 @@ +// +// DetailsViewController.swift +// WOWCardStackView +// +// Created by Zhou Hao on 17/3/17. +// Copyright © 2017 CocoaPods. All rights reserved. +// + +import UIKit +import WOWCardStackView + +class DetailsViewController: UIViewController, CardStackViewDataSource { + + @IBOutlet weak var cardStackView: CardStackView! + var id: Int! + var orderNo: Int = 5 + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "\(id!)" + + cardStackView.register(nib: UINib(nibName: "MyCard", bundle: nil)) + cardStackView.dataSource = self + + } + + func nextCard(in: CardStackView) -> CardView? { + let card = cardStackView.dequeueCardView() as! MyCard + card.numberLabel.text = "\(orderNo)" + orderNo += 1 + return card + } + + func cardStackView(_ cardStackView: CardStackView, cardAt index: Int) -> CardView { + let card = cardStackView.dequeueCardView() as! MyCard + card.numberLabel.text = "\(index)" + return card + } + + func numOfCardInStackView(_ cardStackView: CardStackView) -> Int { + return 5 + } + +} diff --git a/Example/WOWCardStackView/MyCard.swift b/Example/WOWCardStackView/MyCard.swift index 5d48b96..81c8790 100644 --- a/Example/WOWCardStackView/MyCard.swift +++ b/Example/WOWCardStackView/MyCard.swift @@ -11,5 +11,17 @@ import WOWCardStackView class MyCard: CardView { @IBOutlet weak var numberLabel: UILabel! + + var id: Int + + init(id: Int) { + self.id = id + super.init(frame: CGRect.zero) + } + + required init?(coder aDecoder: NSCoder) { + self.id = 0 + super.init(coder: aDecoder) + } } diff --git a/Example/WOWCardStackView/MyCard.xib b/Example/WOWCardStackView/MyCard.xib index cb161db..df2aebd 100644 --- a/Example/WOWCardStackView/MyCard.xib +++ b/Example/WOWCardStackView/MyCard.xib @@ -12,11 +12,21 @@ - + - - - + + + + + + @@ -39,8 +53,12 @@ - + + + + + diff --git a/Example/WOWCardStackView/ViewController.swift b/Example/WOWCardStackView/ViewController.swift index 68886cf..e149ccb 100644 --- a/Example/WOWCardStackView/ViewController.swift +++ b/Example/WOWCardStackView/ViewController.swift @@ -9,7 +9,7 @@ import UIKit import WOWCardStackView -class ViewController: UIViewController, CardStackViewDataSource { +class ViewController: UIViewController, CardStackViewDataSource, CardStackViewDelegate { @IBOutlet weak var cardStackView: CardStackView! var orderNo: Int = 3 @@ -17,27 +17,50 @@ class ViewController: UIViewController, CardStackViewDataSource { override func viewDidLoad() { super.viewDidLoad() - cardStackView.register(nib: UINib(nibName: "MyCard", bundle: nil)) cardStackView.dataSource = self - cardStackView.reloadData() + cardStackView.delegate = self } func nextCard(in: CardStackView) -> CardView? { - let card = cardStackView.dequeueCardView() as! MyCard - card.numberLabel.text = "\(orderNo)" + let card = createCard(order: orderNo) orderNo += 1 return card } func cardStackView(_ cardStackView: CardStackView, cardAt index: Int) -> CardView { - let card = cardStackView.dequeueCardView() as! MyCard - card.numberLabel.text = "\(index)" - return card + return createCard(order: index) } func numOfCardInStackView(_ cardStackView: CardStackView) -> Int { return 3 } + + public func cardStackView(_: CardStackView, didSelect card: CardView) { + if let card = card as? MyCard { + print("Clicked: \(card.id)") + + if let details = self.storyboard?.instantiateViewController(withIdentifier: "DetailsViewController") as? DetailsViewController { + details.id = card.id + self.navigationController?.pushViewController(details, animated: true) + } + } + } + + func createCard(order: Int) -> MyCard { + let card = MyCard(id: order) + card.id = order + let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) + label.font = UIFont(name: "Arial", size: 28) + label.text = "\(order)" + label.textAlignment = .center + label.textColor = UIColor.white + card.addSubview(label) + card.backgroundColor = UIColor.red + card.borderWidth = 1.0 + card.borderColor = UIColor.lightGray + card.isShadowed = true + return card + } } diff --git a/Example/WOWCardStackView/placeholder.jpg b/Example/WOWCardStackView/placeholder.jpg new file mode 100644 index 0000000..fdf7fb5 Binary files /dev/null and b/Example/WOWCardStackView/placeholder.jpg differ diff --git a/WOWCardStackView.podspec b/WOWCardStackView.podspec index 0ef453a..effd5d6 100644 --- a/WOWCardStackView.podspec +++ b/WOWCardStackView.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'WOWCardStackView' - s.version = '0.1.2' + s.version = '0.1.3' s.summary = 'Swapable Card Stack View in Swift 3.0.' # This description is used to generate tags and improve search results. diff --git a/WOWCardStackView/Classes/CardStackView.swift b/WOWCardStackView/Classes/CardStackView.swift index c03424e..52812e7 100644 --- a/WOWCardStackView/Classes/CardStackView.swift +++ b/WOWCardStackView/Classes/CardStackView.swift @@ -14,15 +14,21 @@ public protocol CardStackViewDataSource: class { func numOfCardInStackView(_ cardStackView: CardStackView) -> Int } -public protocol CardStackDelegate: class { - func cardStackView(_: CardStackView, didSelectCardAt: Int) +public protocol CardStackViewDelegate: class { + func cardStackView(_: CardStackView, didSelect card: CardView) } @IBDesignable public class CardStackView: UIView, CardViewDelegate { // MARK: - Properties - public weak var dataSource: CardStackViewDataSource? // TODO: add to dataSource in Inspector + public weak var dataSource: CardStackViewDataSource? { // TODO: add to dataSource in Inspector + didSet { + reloadData() + } + } + + public weak var delegate: CardStackViewDelegate? // MARK: - Private properties private var nib : UINib? @@ -42,16 +48,6 @@ public class CardStackView: UIView, CardViewDelegate { } } - override init(frame: CGRect) { - super.init(frame: frame) - setup() - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - // MARK: - Public methods public func register(nib: UINib) { self.nib = nib @@ -98,6 +94,10 @@ public class CardStackView: UIView, CardViewDelegate { } } + public func cardViewDidSelected(_ cardView: CardView) { + self.delegate?.cardStackView(self, didSelect: cardView) + } + // MARK: - Override override open func layoutSubviews() { // setup cards frame @@ -113,9 +113,6 @@ public class CardStackView: UIView, CardViewDelegate { } // MARK: - Private methods - func setup() { - } - private func rectAt(index: Int) -> CGRect { if let dataSource = dataSource { diff --git a/WOWCardStackView/Classes/CardView.swift b/WOWCardStackView/Classes/CardView.swift index 29a419c..15761a5 100644 --- a/WOWCardStackView/Classes/CardView.swift +++ b/WOWCardStackView/Classes/CardView.swift @@ -10,12 +10,14 @@ import UIKit public protocol CardViewDelegate: class { func shouldRemoveCardView(_ cardView: CardView) + func cardViewDidSelected(_ cardView: CardView) } @IBDesignable open class CardView: UIView { private var originCenter: CGPoint! + private var dragged: Bool = false weak var delegate: CardViewDelegate? @@ -45,10 +47,11 @@ open class CardView: UIView { } } - override init(frame: CGRect) { + public override init(frame: CGRect) { super.init(frame: frame) setup() } + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() @@ -58,13 +61,26 @@ open class CardView: UIView { let gesture = UIPanGestureRecognizer(target: self, action: #selector(drag(gesture:))) self.addGestureRecognizer(gesture) } - + override open func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) originCenter = self.center + dragged = false } + open override func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + + guard isTopMost() else { + return + } + + if !dragged { + self.delegate?.cardViewDidSelected(self) + } + } + func drag(gesture: UIPanGestureRecognizer) { guard isTopMost() else { @@ -96,9 +112,10 @@ open class CardView: UIView { return } + dragged = true self.center = CGPoint(x: originCenter.x + translation.x, y: originCenter.y + translation.y) } - + //MARK: - Private func isTopMost() -> Bool { return self.superview?.subviews.last == self diff --git a/stack.gif b/stack.gif index dee85d8..e314c86 100644 Binary files a/stack.gif and b/stack.gif differ