From c8442715e8b2c4c64d2b22dece1fead7b7fb74c3 Mon Sep 17 00:00:00 2001 From: Paolo Date: Tue, 31 Oct 2017 15:44:28 +0100 Subject: [PATCH] Demo project improved + Bug Fixes CardPlayer behaviour fix Delegate system clean up Attributes description added Slight animations improvements Code cleanup --- Cards.podspec | 2 +- Cards/Sources/Animator.swift | 16 +- Cards/Sources/Card.swift | 96 ++++-- Cards/Sources/CardArticle.swift | 42 ++- Cards/Sources/CardGroup.swift | 42 ++- Cards/Sources/CardGroupSliding.swift | 34 +- Cards/Sources/CardHighlight.swift | 57 ++-- Cards/Sources/CardPlayer.swift | 107 ++++-- Cards/Sources/DetailViewController.swift | 24 +- Demo/Demo.xcodeproj/project.pbxproj | 54 ++- .../xcdebugger/Breakpoints_v2.xcbkptlist | 308 +++++++++--------- .../Base.lproj/LaunchScreen.storyboard | 25 ++ .../Storyboards/Base.lproj/Main.storyboard | 251 ++++++++++++++ .../ArticleViewController.swift | 27 ++ .../ViewControllers/GroupViewController.swift | 42 +++ .../HighlightViewController.swift | 64 ++++ .../PlayerViewController.swift | 38 +++ README.md | 4 +- 18 files changed, 920 insertions(+), 313 deletions(-) create mode 100644 Demo/Demo/Storyboards/Base.lproj/LaunchScreen.storyboard create mode 100755 Demo/Demo/Storyboards/Base.lproj/Main.storyboard create mode 100644 Demo/Demo/ViewControllers/ArticleViewController.swift create mode 100644 Demo/Demo/ViewControllers/GroupViewController.swift create mode 100644 Demo/Demo/ViewControllers/HighlightViewController.swift create mode 100644 Demo/Demo/ViewControllers/PlayerViewController.swift diff --git a/Cards.podspec b/Cards.podspec index 76da35a..b929160 100644 --- a/Cards.podspec +++ b/Cards.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Cards' - s.version = '1.2.4' + s.version = '1.2.5' s.summary = 'Awesome iOS 11 appstore cards in swift 4.' s.homepage = 'https://github.com/PaoloCuscela/Cards' s.screenshots = 'https://raw.githubusercontent.com/PaoloCuscela/Cards/master/Images/Overview.png', 'https://raw.githubusercontent.com/PaoloCuscela/Cards/master/Images/CardGroupSliding.gif' diff --git a/Cards/Sources/Animator.swift b/Cards/Sources/Animator.swift index 075f70f..5b68c74 100644 --- a/Cards/Sources/Animator.swift +++ b/Cards/Sources/Animator.swift @@ -12,7 +12,7 @@ class Animator: NSObject, UIViewControllerAnimatedTransitioning { fileprivate var presenting: Bool fileprivate var velocity = 0.6 - var bounceIntensity: CGFloat = 0.1 + var bounceIntensity: CGFloat = 0.07 var card: Card init(presenting: Bool, from card: Card) { @@ -34,10 +34,11 @@ class Animator: NSObject, UIViewControllerAnimatedTransitioning { guard presenting else { // Detail View Controller Dismiss Animations + card.isPresenting = false let superVC = to let detailVC = from as! DetailViewController - let cardBackgroundFrame = detailVC.scrollView.convert(detailVC.cardBackground.frame, to: nil) + let cardBackgroundFrame = detailVC.scrollView.convert(card.backgroundIV.frame, to: nil) let bounce = self.bounceTransform(cardBackgroundFrame, to: card.originalFrame) // Blur and fade with completion @@ -45,10 +46,12 @@ class Animator: NSObject, UIViewControllerAnimatedTransitioning { detailVC.blurView.alpha = 0 detailVC.snap.alpha = 0 + self.card.backgroundIV.layer.cornerRadius = self.card.cardRadius }, completion: { _ in - self.card.addSubview(detailVC.cardBackground) + detailVC.layout(self.card.originalFrame, isPresenting: false, isAnimating: false) + self.card.addSubview(detailVC.card.backgroundIV) transitionContext.completeTransition(true) }) @@ -69,12 +72,13 @@ class Animator: NSObject, UIViewControllerAnimatedTransitioning { } // Detail View Controller Present Animations + card.isPresenting = true let detailVC = to as! DetailViewController - let bounce = self.bounceTransform(card.originalFrame, to: UIScreen.main.bounds) + let bounce = self.bounceTransform(card.originalFrame, to: card.backgroundIV.frame) container.bringSubview(toFront: detailVC.view) - detailVC.cardBackground = card.backgroundIV + detailVC.card = card detailVC.layout(card.originalFrame, isPresenting: false) // Blur and fade with completion @@ -83,9 +87,11 @@ class Animator: NSObject, UIViewControllerAnimatedTransitioning { self.card.transform = CGAffineTransform.identity // Reset card identity after push back on tap detailVC.blurView.alpha = 1 detailVC.snap.alpha = 1 + self.card.backgroundIV.layer.cornerRadius = 0 }, completion: { _ in + detailVC.layout(self.card.originalFrame, isPresenting: true, isAnimating: false, transform: .identity) transitionContext.completeTransition(true) }) diff --git a/Cards/Sources/Card.swift b/Cards/Sources/Card.swift index 3c8aa87..809a606 100644 --- a/Cards/Sources/Card.swift +++ b/Cards/Sources/Card.swift @@ -30,25 +30,67 @@ import UIKit @IBDesignable open class Card: UIView, CardDelegate { // Storyboard Inspectable vars - @IBInspectable public var shadowBlur: CGFloat = 14 - @IBInspectable public var shadowOpacity: Float = 0.6 - @IBInspectable public var shadowColor: UIColor = UIColor.gray - @IBInspectable public var backgroundImage: UIImage? + /** + Color for the card's labels. + */ @IBInspectable public var textColor: UIColor = UIColor.black - @IBInspectable public var cardRadius: CGFloat = 20 + /** + Amount of blur for the card's shadow. + */ + @IBInspectable public var shadowBlur: CGFloat = 14 { + didSet{ + self.layer.shadowRadius = shadowBlur + } + } + /** + Alpha of the card's shadow. + */ + @IBInspectable public var shadowOpacity: Float = 0.6 { + didSet{ + self.layer.shadowOpacity = shadowOpacity + } + } + /** + Color of the card's shadow. + */ + @IBInspectable public var shadowColor: UIColor = UIColor.gray { + didSet{ + self.layer.shadowColor = shadowColor.cgColor + } + } + /** + The image to display in the background. + */ + @IBInspectable public var backgroundImage: UIImage? { + didSet{ + self.backgroundIV.image = backgroundImage + } + } + /** + Corner radius of the card. + */ + @IBInspectable public var cardRadius: CGFloat = 20{ + didSet{ + self.layer.cornerRadius = cardRadius + } + } + /** + Insets between card's content and edges ( in percentage ) + */ @IBInspectable public var contentInset: CGFloat = 6 { didSet { insets = LayoutHelper(rect: originalFrame).X(contentInset) } } - + /** + Color of the card's background. + */ override open var backgroundColor: UIColor? { didSet(new) { if let color = new { backgroundIV.backgroundColor = color } if backgroundColor != UIColor.clear { backgroundColor = UIColor.clear } } } - /** detailView -> The view to show after presenting detail; from -> Your current ViewController (self) */ @@ -56,15 +98,19 @@ import UIKit self.superVC = superVC self.detailView = detailView } - + /** + If the card should display parallax effect. + */ public var hasParallax: Bool = true { didSet { if self.motionEffects.isEmpty && hasParallax { goParallax() } else if !hasParallax && !motionEffects.isEmpty { motionEffects.removeAll() } } } - - var delegate: CardDelegate? + /** + Delegate for the card. Should extend your VC with CardDelegate. + */ + public var delegate: CardDelegate? //Private Vars fileprivate var tap = UITapGestureRecognizer() @@ -74,6 +120,7 @@ import UIKit var originalFrame = CGRect.zero var backgroundIV = UIImageView() var insets = CGFloat() + var isPresenting = false //MARK: - View Life Cycle @@ -102,13 +149,17 @@ import UIKit // Adding Subviews self.addSubview(backgroundIV) - delegate = self backgroundIV.isUserInteractionEnabled = true - self.backgroundColor = UIColor.white + + if backgroundIV.backgroundColor == nil { + backgroundIV.backgroundColor = UIColor.white + super.backgroundColor = UIColor.clear + } } override open func draw(_ rect: CGRect) { super.draw(rect) + originalFrame = rect self.layer.shadowOpacity = shadowOpacity self.layer.shadowColor = shadowColor.cgColor @@ -121,25 +172,21 @@ import UIKit backgroundIV.clipsToBounds = true backgroundIV.contentMode = .scaleAspectFill - layout(rect) - - originalFrame = rect + backgroundIV.frame.origin = bounds.origin + backgroundIV.frame.size = CGSize(width: bounds.width, height: bounds.height) contentInset = 6 } //MARK: - Layout - func layout(_ rect: CGRect){ - - backgroundIV.frame.origin = rect.origin - backgroundIV.frame.size = CGSize(width: rect.width, height: rect.height) - } + func layout(animating: Bool = true){ } //MARK: - Actions @objc func cardTapped(){ + self.delegate?.cardDidTapInside?(card: self) if let vc = superVC { @@ -147,7 +194,7 @@ import UIKit vc.present(self.detailVC, animated: true, completion: nil) } else { - resetAnimated { } + resetAnimated() } } @@ -159,12 +206,9 @@ import UIKit UIView.animate(withDuration: 0.2, animations: { self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) }) } - private func resetAnimated(_ completion: @escaping () -> ()) { + private func resetAnimated() { - UIView.animate(withDuration: 0.2, animations: { self.transform = CGAffineTransform.identity }) { _ in - self.delegate?.cardDidTapInside?(card: self) - completion() - } + UIView.animate(withDuration: 0.2, animations: { self.transform = CGAffineTransform.identity }) } func goParallax() { diff --git a/Cards/Sources/CardArticle.swift b/Cards/Sources/CardArticle.swift index fb257c2..819dcb5 100644 --- a/Cards/Sources/CardArticle.swift +++ b/Cards/Sources/CardArticle.swift @@ -11,12 +11,26 @@ import UIKit @IBDesignable open class CardArticle: Card { // SB Vars + /** + Text of the title label. + */ @IBInspectable public var title: String = "The Art of the Impossible" + /** + Max font size the title label. + */ @IBInspectable public var titleSize: CGFloat = 26 + /** + Text of the subtitle label. + */ @IBInspectable public var subtitle: String = "Inside the extraordinary world of Monument Valley 2" + /** + Max font size the subtitle label. + */ @IBInspectable public var subtitleSize: CGFloat = 17 + /** + Text of the category label. + */ @IBInspectable public var category: String = "world premiere" - @IBInspectable public var blurEffect: UIBlurEffectStyle = UIBlurEffectStyle.extraLight //Priv Vars var titleLbl = UILabel () @@ -36,7 +50,6 @@ import UIKit override func initialize() { super.initialize() - self.delegate = self backgroundIV.addSubview(titleLbl) backgroundIV.addSubview(subtitleLbl) backgroundIV.addSubview(categoryLbl) @@ -78,21 +91,14 @@ import UIKit subtitleLbl.numberOfLines = 0 subtitleLbl.textAlignment = .left - self.layout(backgroundIV.frame) + self.layout() } - override func cardTapped() { - super.cardTapped() - delegate?.cardDidTapInside?(card: self) - } - - - override func layout(_ rect: CGRect) { + override func layout(animating: Bool = true) { + super.layout(animating: animating) - super.layout(rect) - - let gimme = LayoutHelper(rect: rect) + let gimme = LayoutHelper(rect: backgroundIV.bounds) categoryLbl.frame = CGRect(x: insets, y: insets, @@ -103,23 +109,15 @@ import UIKit y: gimme.Y(1, from: categoryLbl), width: gimme.X(80), height: gimme.Y(17)) - + subtitleLbl.frame = CGRect(x: insets, y: gimme.RevY(0, height: gimme.Y(14)) - insets, width: gimme.X(80), height: gimme.Y(14)) titleLbl.sizeToFit() - } } -extension CardArticle { - - public func cardDidShowDetailView(card: Card) { layout(backgroundIV.bounds) } - public func cardWillCloseDetailView(card: Card) { layout(originalFrame) } - -} - diff --git a/Cards/Sources/CardGroup.swift b/Cards/Sources/CardGroup.swift index cf51686..5da4954 100644 --- a/Cards/Sources/CardGroup.swift +++ b/Cards/Sources/CardGroup.swift @@ -11,10 +11,25 @@ import UIKit @IBDesignable open class CardGroup: Card { // SB Vars + /** + Text of the title label. + */ @IBInspectable public var title: String = "Welcome to XI Cards !" + /** + Max font size the title label. + */ @IBInspectable public var titleSize: CGFloat = 26 + /** + Text of the subtitle label. + */ @IBInspectable public var subtitle: String = "from the editors" + /** + Max font size the subtitle label. + */ @IBInspectable public var subtitleSize: CGFloat = 26 + /** + Style for the blur effect. + */ @IBInspectable public var blurEffect: UIBlurEffectStyle = .extraLight //Priv Vars @@ -37,7 +52,6 @@ import UIKit override func initialize() { super.initialize() - self.delegate = self vibrancyV = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: blurEffect))) backgroundIV.addSubview(blurV) blurV.contentView.addSubview(titleLbl) @@ -70,17 +84,17 @@ import UIKit let blur = UIBlurEffect(style: blurEffect) blurV.effect = blur - layout(backgroundIV.bounds) + layout() } - override func layout(_ rect: CGRect) { - super.layout(rect) + override func layout(animating: Bool = true) { + super.layout(animating: animating) - let gimme = LayoutHelper(rect: rect) + let gimme = LayoutHelper(rect: backgroundIV.bounds) blurV.frame = CGRect(x: 0, y: 0, - width: rect.width, + width: backgroundIV.bounds.width, height: gimme.Y(42)) vibrancyV.frame = blurV.frame @@ -106,20 +120,4 @@ import UIKit } } -extension CardGroup { - - public func cardIsShowingDetail(card: Card) { - layout(backgroundIV.bounds) - } - - public func cardIsHidingDetail(card: Card) { - layout(backgroundIV.bounds) - } - - public func cardDidShowDetailView(card: Card) { - layout(backgroundIV.frame) - } - -} - diff --git a/Cards/Sources/CardGroupSliding.swift b/Cards/Sources/CardGroupSliding.swift index 5acfdaa..fab2912 100644 --- a/Cards/Sources/CardGroupSliding.swift +++ b/Cards/Sources/CardGroupSliding.swift @@ -10,9 +10,18 @@ import UIKit @IBDesignable open class CardGroupSliding: CardGroup { + /** + Size for the collection view items. + */ @IBInspectable public var iconsSize: CGFloat = 80 + /** + Corner radius of the collection view items + */ @IBInspectable public var iconsRadius: CGFloat = 40 + /** + Data source for the collection view. + */ public var icons: [UIImage]? // Priv vars @@ -59,37 +68,24 @@ import UIKit super.draw(rect) subtitleLbl.textColor = textColor.withAlphaComponent(0.4) - layout(backgroundIV.bounds, animationHasEnded: true) + layout(animating: false) } - func layout(_ rect: CGRect, animationHasEnded: Bool) { - super.layout(rect) - - guard animationHasEnded else { return } + override func layout(animating: Bool) { + super.layout(animating: animating) - let gimme = LayoutHelper(rect: rect) + let gimme = LayoutHelper(rect: backgroundIV.bounds) slidingCV.frame = CGRect(x: 0, y: gimme.Y(5, from: titleLbl), width: backgroundIV.frame.width, - height: rect.height - (blurV.frame.height - insets ) ) - } - - public func cardDidCloseDetailView(card: Card) { - cardDidCloseDetailView(card: card) - self.layout(backgroundIV.bounds, animationHasEnded: true) + height: backgroundIV.bounds.height - blurV.frame.height ) } - public override func cardDidShowDetailView(card: Card) { - super.cardDidShowDetailView(card: card) - self.layout(backgroundIV.bounds, animationHasEnded: true) - } - - //MARK: - Sliding Logic public func startSlide() { - timer = Timer.scheduledTimer(timeInterval: 0.03, target: self, selector: #selector(self.slide), userInfo: nil, repeats: true) + timer = Timer.scheduledTimer(timeInterval: 0.04, target: self, selector: #selector(self.slide), userInfo: nil, repeats: true) } public func stopSlide() { diff --git a/Cards/Sources/CardHighlight.swift b/Cards/Sources/CardHighlight.swift index c75c88a..466d9ba 100644 --- a/Cards/Sources/CardHighlight.swift +++ b/Cards/Sources/CardHighlight.swift @@ -10,15 +10,46 @@ import UIKit @IBDesignable open class CardHighlight: Card { + /** + Text of the title label. + */ @IBInspectable public var title: String = "welcome \nto \ncards !" + /** + Max font size the title label. + */ @IBInspectable public var titleSize:CGFloat = 26 + /** + Text of the title label of the item at the bottom. + */ @IBInspectable public var itemTitle: String = "Flappy Bird" + /** + Max font size the subtitle label of the item at the bottom. + */ @IBInspectable public var itemTitleSize: CGFloat = 16 + /** + Text of the subtitle label of the item at the bottom. + */ @IBInspectable public var itemSubtitle: String = "Flap that !" + /** + Max font size the subtitle label of the item at the bottom. + */ @IBInspectable public var itemSubtitleSize: CGFloat = 14 + /** + Image displayed in the icon ImageView. + */ @IBInspectable public var icon: UIImage? + /** + Corner radius for the icon ImageView + */ @IBInspectable public var iconRadius: CGFloat = 16 - @IBInspectable public var buttonText: String = "view" + /** + Text for the card's button. + */ + @IBInspectable public var buttonText: String = "view" { + didSet{ + self.setNeedsDisplay() + } + } //Priv Vars private var iconIV = UIImageView() @@ -45,7 +76,6 @@ import UIKit override func initialize() { super.initialize() - self.delegate = self actionBtn.addTarget(self, action: #selector(buttonTapped), for: UIControlEvents.touchUpInside) backgroundIV.addSubview(iconIV) @@ -105,14 +135,14 @@ import UIKit btnWidth = CGFloat((buttonText.characters.count + 2) * 10) - layout(backgroundIV.frame) + layout() } - internal override func layout(_ rect: CGRect) { - super.layout(rect) + override func layout(animating: Bool = true) { + super.layout(animating: animating) - let gimme = LayoutHelper(rect: rect) + let gimme = LayoutHelper(rect: backgroundIV.frame) iconIV.frame = CGRect(x: insets, y: insets, @@ -120,7 +150,7 @@ import UIKit height: gimme.Y(25)) titleLbl.frame.origin = CGPoint(x: insets, y: gimme.Y(5, from: iconIV)) - titleLbl.frame.size.width = (originalFrame.width * 0.65) + ((rect.width - originalFrame.width)/3) + titleLbl.frame.size.width = (originalFrame.width * 0.65) + ((backgroundIV.bounds.width - originalFrame.width)/3) titleLbl.frame.size.height = gimme.Y(35) itemSubtitleLbl.sizeToFit() @@ -148,7 +178,6 @@ import UIKit width: btnWidth, height: 32) actionBtn.layer.cornerRadius = actionBtn.layer.bounds.height/2 - } //Actions @@ -165,17 +194,5 @@ import UIKit } } -extension CardHighlight { - - public func cardIsShowingDetail(card: Card) { - layout(backgroundIV.frame) - } - - public func cardIsHidingDetail(card: Card) { - layout(backgroundIV.frame) - } - -} - diff --git a/Cards/Sources/CardPlayer.swift b/Cards/Sources/CardPlayer.swift index 8e82d20..a201339 100644 --- a/Cards/Sources/CardPlayer.swift +++ b/Cards/Sources/CardPlayer.swift @@ -12,21 +12,61 @@ import Player @IBDesignable open class CardPlayer: Card { + /** + Text of the title label. + */ @IBInspectable public var title: String = "Big Buck Bunny" + /** + Max font size of the title label. + */ @IBInspectable public var titleSize: CGFloat = 26 + /** + Text of the subtitle label. + */ @IBInspectable public var subtitle: String = "Inside the extraordinary world of Buck Bunny" + /** + Max font size of the subtitle label. + */ @IBInspectable public var subtitleSize: CGFloat = 19 + /** + Text of the category label. + */ @IBInspectable public var category: String = "today's movie" + /** + Size for the play button in the player. + */ @IBInspectable public var playBtnSize: CGFloat = 56 + /** + Image shown in the play button. + */ @IBInspectable public var playImage: UIImage? + /** + Image shown before the player is loaded. + */ @IBInspectable public var playerCover: UIImage? + /** + If the player should start the playback when is ready. + */ @IBInspectable public var isAutoplayEnabled: Bool = false + /** + If the player should restart the playback when it ends. + */ @IBInspectable public var shouldRestartVideoWhenPlaybackEnds: Bool = true + /** + Source for the video ( streaming or local ). + */ @IBInspectable public var videoSource: URL? { didSet { player.url = videoSource } } - open var player = Player() // Player provided by Patrik Piemonte + /** + Required. View controller that should display the player. + */ + public func shouldDisplayPlayer( from vc: UIViewController ) { + vc.addChildViewController(player) + } + + private var player = Player() // Player provided by Patrik Piemonte private var titleLbl = UILabel () private var subtitleLbl = UILabel() @@ -125,23 +165,23 @@ import Player subtitleLbl.numberOfLines = 0 subtitleLbl.textAlignment = .left - self.layout(rect, showingDetail: false) + self.layout() } - func layout(_ rect: CGRect, showingDetail: Bool = false) { - super.layout(rect) + override func layout(animating: Bool = true) { + super.layout(animating: animating) - let gimme = LayoutHelper(rect: rect) + let gimme = LayoutHelper(rect: backgroundIV.bounds) - let aspect1016 = rect.width * (10/16) - let aspect921 = rect.width * (9/21) + let aspect1016 = backgroundIV.bounds.width * (10/16) + let aspect921 = backgroundIV.bounds.width * (9/21) let move = ( aspect1016 - aspect921 ) * 2 - subtitleLbl.transform = showingDetail ? CGAffineTransform(translationX: 0, y: move) : CGAffineTransform.identity - //backgroundIV.frame.size.height = originalFrame.height + ( showingDetail ? move : 0 ) + subtitleLbl.transform = isPresenting ? CGAffineTransform(translationX: 0, y: move) : CGAffineTransform.identity + backgroundIV.frame.size.height = originalFrame.height + ( isPresenting ? move/2 : 0 ) player.view.frame.origin = CGPoint.zero - player.view.frame.size = CGSize(width: rect.width, height: showingDetail ? aspect1016 : aspect921 ) + player.view.frame.size = CGSize(width: backgroundIV.bounds.width, height: isPresenting ? aspect1016 : aspect921 ) playerCoverIV.frame = player.view.bounds @@ -151,7 +191,7 @@ import Player categoryLbl.frame.origin.y = gimme.Y(3, from: player.view) titleLbl.frame.origin.y = gimme.Y(0, from: categoryLbl) titleLbl.sizeToFit() - + categoryLbl.frame = CGRect(x: insets, y: gimme.Y(3, from: player.view), width: gimme.X(80), @@ -169,28 +209,45 @@ import Player height: gimme.Y(12)) } + //MARK: - Actions - @objc func playTapped() { - delegate?.cardPlayerDidPlay?(card: self) - player.playFromCurrentTime() + public func play() { + player.playFromCurrentTime() UIView.animate(withDuration: 0.2) { self.playPauseV.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) self.playPauseV.alpha = 0 } } - @objc func playerTapped() { - delegate?.cardPlayerDidPause?(card: self) - player.pause() + public func pause() { + player.pause() UIView.animate(withDuration: 0.1) { self.playPauseV.transform = CGAffineTransform.identity self.playPauseV.alpha = 1 } } + public func stop() { + + pause() + player.stop() + } + + @objc func playTapped() { + + play() + delegate?.cardPlayerDidPlay?(card: self) + } + + @objc func playerTapped() { + + pause() + delegate?.cardPlayerDidPause?(card: self) + } + open override func touchesBegan(_ touches: Set, with event: UIEvent?) { if touches.first?.view == player.view || touches.first?.view == playPauseV.contentView { playerTapped() } else { super.touchesBegan(touches, with: event) } @@ -213,9 +270,9 @@ extension CardPlayer: PlayerDelegate { if isAutoplayEnabled { - playTapped() + play() } else { - player.pause() + pause() } } @@ -238,16 +295,4 @@ extension CardPlayer: PlayerPlaybackDelegate { public func playerPlaybackWillStartFromBeginning(_ player: Player) { } } -extension CardPlayer { - - public func cardIsHidingDetail(card: Card) { - layout(backgroundIV.frame, showingDetail: false) - } - - public func cardIsShowingDetail(card: Card) { - layout(backgroundIV.frame, showingDetail: true) - } - -} - diff --git a/Cards/Sources/DetailViewController.swift b/Cards/Sources/DetailViewController.swift index 53ccd90..e898998 100644 --- a/Cards/Sources/DetailViewController.swift +++ b/Cards/Sources/DetailViewController.swift @@ -14,9 +14,9 @@ internal class DetailViewController: UIViewController { var scrollView = UIScrollView() var originalFrame = CGRect.zero var snap = UIView() - var cardBackground: UIView! { + var card: Card! { didSet{ - scrollView.addSubview(cardBackground) + scrollView.addSubview(card.backgroundIV) } } @@ -32,12 +32,13 @@ internal class DetailViewController: UIViewController { if let detail = detailView { scrollView.addSubview(detail) + detail.autoresizingMask = .flexibleWidth detail.alpha = 0 } blurView.frame = self.view.bounds - scrollView.layer.backgroundColor = UIColor.white.cgColor + scrollView.layer.backgroundColor = detailView?.backgroundColor?.cgColor ?? UIColor.white.cgColor scrollView.layer.cornerRadius = 20 scrollView.delegate = self @@ -54,10 +55,10 @@ internal class DetailViewController: UIViewController { detail.alpha = 1 detail.frame = CGRect(x: 0, - y: cardBackground.bounds.maxY, + y: card.backgroundIV.bounds.maxY, width: scrollView.frame.width, height: detail.frame.height) - + scrollView.contentSize = CGSize(width: scrollView.bounds.width, height: detail.frame.maxY) } @@ -70,12 +71,13 @@ internal class DetailViewController: UIViewController { //MARK: - Layout & Animations for the content ( rect = Scrollview + card + detail ) - func layout(_ rect: CGRect, isPresenting: Bool, transform: CGAffineTransform = CGAffineTransform.identity){ + func layout(_ rect: CGRect, isPresenting: Bool, isAnimating: Bool = true, transform: CGAffineTransform = CGAffineTransform.identity){ guard isPresenting else { scrollView.frame = rect.applying(transform) - cardBackground.frame = scrollView.bounds + card.backgroundIV.frame = scrollView.bounds + card.layout(animating: isAnimating) return } @@ -84,9 +86,11 @@ internal class DetailViewController: UIViewController { scrollView.frame.origin.y = 40 scrollView.frame = scrollView.frame.applying(transform) - cardBackground.frame.origin = scrollView.bounds.origin - cardBackground.frame.size = CGSize( width: scrollView.bounds.width, - height: cardBackground.bounds.height) + card.backgroundIV.frame.origin = scrollView.bounds.origin + card.backgroundIV.frame.size = CGSize( width: scrollView.bounds.width, + height: card.backgroundIV.bounds.height) + card.layout(animating: isAnimating) + } } diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 0cc6873..645fc6c 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -7,24 +7,30 @@ objects = { /* Begin PBXBuildFile section */ - 6D3CD33E1F9BDDD600C0592C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D3CD33D1F9BDDD600C0592C /* Main.storyboard */; }; - 6D3CD3401F9BDDE300C0592C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D3CD33F1F9BDDE300C0592C /* ViewController.swift */; }; + 6D0C91591FA8BF350073554B /* ArticleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0C91581FA8BF350073554B /* ArticleViewController.swift */; }; + 6D37D92C1FA8852C00B33EA0 /* GroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D37D92B1FA8852C00B33EA0 /* GroupViewController.swift */; }; 6D3CD3421F9BDE0D00C0592C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D3CD3411F9BDE0D00C0592C /* Assets.xcassets */; }; 6D436D571F9BD34600B05FA6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D436D561F9BD34600B05FA6 /* AppDelegate.swift */; }; 6D436D611F9BD34600B05FA6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D436D5F1F9BD34600B05FA6 /* LaunchScreen.storyboard */; }; + 6D965BA21FA7974100705AAA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D965BA01FA7974100705AAA /* Main.storyboard */; }; + 6D965BA41FA79A6300705AAA /* HighlightViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D965BA31FA79A6300705AAA /* HighlightViewController.swift */; }; + 6D965BA81FA7B6DD00705AAA /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D965BA71FA7B6DD00705AAA /* PlayerViewController.swift */; }; 6FDABBFFC80A25A8DEEFE3E3 /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DB13C5E8ADDE29D425A8FEC /* Pods_Demo.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 38CFFDBE6D3C33B1A464184C /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = ""; }; + 6D0C91581FA8BF350073554B /* ArticleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleViewController.swift; sourceTree = ""; }; + 6D37D92B1FA8852C00B33EA0 /* GroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupViewController.swift; sourceTree = ""; }; 6D3CD3321F9BD40B00C0592C /* Cards.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Cards.podspec; path = ../Cards.podspec; sourceTree = ""; }; - 6D3CD33D1F9BDDD600C0592C /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; - 6D3CD33F1F9BDDE300C0592C /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 6D3CD3411F9BDE0D00C0592C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6D436D531F9BD34600B05FA6 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6D436D561F9BD34600B05FA6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 6D436D601F9BD34600B05FA6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 6D436D621F9BD34600B05FA6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D965BA11FA7974100705AAA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D965BA31FA79A6300705AAA /* HighlightViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightViewController.swift; sourceTree = ""; }; + 6D965BA71FA7B6DD00705AAA /* PlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; }; 8DB13C5E8ADDE29D425A8FEC /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A67AFDB912F87244FCB0C745 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -64,15 +70,34 @@ isa = PBXGroup; children = ( 6D436D561F9BD34600B05FA6 /* AppDelegate.swift */, - 6D3CD33F1F9BDDE300C0592C /* ViewController.swift */, - 6D3CD33D1F9BDDD600C0592C /* Main.storyboard */, + 6D965BA51FA79A6800705AAA /* ViewControllers */, + 6D965BA61FA79A8D00705AAA /* Storyboards */, 6D3CD3411F9BDE0D00C0592C /* Assets.xcassets */, - 6D436D5F1F9BD34600B05FA6 /* LaunchScreen.storyboard */, 6D436D621F9BD34600B05FA6 /* Info.plist */, ); path = Demo; sourceTree = ""; }; + 6D965BA51FA79A6800705AAA /* ViewControllers */ = { + isa = PBXGroup; + children = ( + 6D965BA31FA79A6300705AAA /* HighlightViewController.swift */, + 6D965BA71FA7B6DD00705AAA /* PlayerViewController.swift */, + 6D37D92B1FA8852C00B33EA0 /* GroupViewController.swift */, + 6D0C91581FA8BF350073554B /* ArticleViewController.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; + 6D965BA61FA79A8D00705AAA /* Storyboards */ = { + isa = PBXGroup; + children = ( + 6D965BA01FA7974100705AAA /* Main.storyboard */, + 6D436D5F1F9BD34600B05FA6 /* LaunchScreen.storyboard */, + ); + path = Storyboards; + sourceTree = ""; + }; 8F906564362B7B6F05CF3756 /* Pods */ = { isa = PBXGroup; children = ( @@ -152,7 +177,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6D3CD33E1F9BDDD600C0592C /* Main.storyboard in Resources */, + 6D965BA21FA7974100705AAA /* Main.storyboard in Resources */, 6D3CD3421F9BDE0D00C0592C /* Assets.xcassets in Resources */, 6D436D611F9BD34600B05FA6 /* LaunchScreen.storyboard in Resources */, ); @@ -221,8 +246,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6D3CD3401F9BDDE300C0592C /* ViewController.swift in Sources */, + 6D37D92C1FA8852C00B33EA0 /* GroupViewController.swift in Sources */, 6D436D571F9BD34600B05FA6 /* AppDelegate.swift in Sources */, + 6D0C91591FA8BF350073554B /* ArticleViewController.swift in Sources */, + 6D965BA41FA79A6300705AAA /* HighlightViewController.swift in Sources */, + 6D965BA81FA7B6DD00705AAA /* PlayerViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -237,6 +265,14 @@ name = LaunchScreen.storyboard; sourceTree = ""; }; + 6D965BA01FA7974100705AAA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D965BA11FA7974100705AAA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/Demo/Demo.xcworkspace/xcuserdata/paolocuscela.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Demo/Demo.xcworkspace/xcuserdata/paolocuscela.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index bbbc009..7f77e06 100644 --- a/Demo/Demo.xcworkspace/xcuserdata/paolocuscela.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Demo/Demo.xcworkspace/xcuserdata/paolocuscela.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -67,86 +67,6 @@ landmarkType = "7"> - - - - - - - - - - - - - - - - - - - - @@ -266,11 +186,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "../Cards/Sources/Card.swift" - timestampString = "530654345.140922" + timestampString = "531153197.905664" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "140" - endingLineNumber = "140" + startingLineNumber = "186" + endingLineNumber = "186" landmarkName = "Card" landmarkType = "3"> @@ -314,11 +234,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "../Cards/Sources/Card.swift" - timestampString = "530654345.140993" + timestampString = "531153197.905728" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "139" - endingLineNumber = "139" + startingLineNumber = "185" + endingLineNumber = "185" landmarkName = "Card" landmarkType = "3"> @@ -458,59 +378,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "../Cards/Sources/Card.swift" - timestampString = "530654345.141212" + timestampString = "531153197.905836" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "143" - endingLineNumber = "143" - landmarkName = "cardTapped()" - landmarkType = "7"> - - - - - - - - - - @@ -618,11 +490,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "../Cards/Sources/Card.swift" - timestampString = "530654345.141508" + timestampString = "531153197.905943" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "200" - endingLineNumber = "200" + startingLineNumber = "244" + endingLineNumber = "244" landmarkName = "Card" landmarkType = "21"> @@ -712,14 +584,158 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "../Cards/Sources/CardPlayer.swift" - timestampString = "530654345.141646" + timestampString = "531153197.90603" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "195" - endingLineNumber = "195" + startingLineNumber = "252" + endingLineNumber = "252" landmarkName = "touchesBegan(_:with:)" landmarkType = "7"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/Demo/Storyboards/Base.lproj/LaunchScreen.storyboard b/Demo/Demo/Storyboards/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f83f6fd --- /dev/null +++ b/Demo/Demo/Storyboards/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/Demo/Storyboards/Base.lproj/Main.storyboard b/Demo/Demo/Storyboards/Base.lproj/Main.storyboard new file mode 100755 index 0000000..12d42fe --- /dev/null +++ b/Demo/Demo/Storyboards/Base.lproj/Main.storyboard @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/Demo/ViewControllers/ArticleViewController.swift b/Demo/Demo/ViewControllers/ArticleViewController.swift new file mode 100644 index 0000000..2278257 --- /dev/null +++ b/Demo/Demo/ViewControllers/ArticleViewController.swift @@ -0,0 +1,27 @@ +// +// ArticleViewController.swift +// Demo +// +// Created by Paolo Cuscela on 31/10/17. +// Copyright © 2017 Paolo Cuscela. All rights reserved. +// + +import UIKit +import Cards + +class ArticleViewController: UIViewController { + + @IBOutlet weak var card: CardArticle! + + override func viewDidLoad() { + super.viewDidLoad() + + let cardContent = storyboard?.instantiateViewController(withIdentifier: "CardContent").view + card.shouldPresent(cardContent, from: self) + + + } + + + +} diff --git a/Demo/Demo/ViewControllers/GroupViewController.swift b/Demo/Demo/ViewControllers/GroupViewController.swift new file mode 100644 index 0000000..ba0d784 --- /dev/null +++ b/Demo/Demo/ViewControllers/GroupViewController.swift @@ -0,0 +1,42 @@ +// +// GroupViewController.swift +// Demo +// +// Created by Paolo Cuscela on 31/10/17. +// Copyright © 2017 Paolo Cuscela. All rights reserved. +// + +import UIKit +import Cards + +class GroupViewController: UIViewController { + + @IBOutlet weak var group: CardGroup! + @IBOutlet weak var sliding: CardGroupSliding! + + override func viewDidLoad() { + super.viewDidLoad() + + let icons: [UIImage] = [ + + UIImage(named: "grBackground")!, + UIImage(named: "background")!, + UIImage(named: "flappy")!, + UIImage(named: "flBackground")!, + UIImage(named: "Icon")!, + UIImage(named: "mvBackground")! + + ] + + sliding.icons = icons + + let groupCardContent = storyboard?.instantiateViewController(withIdentifier: "CardContent").view + group.shouldPresent(groupCardContent, from: self) + + let slidingCardContent = storyboard?.instantiateViewController(withIdentifier: "CardContent").view + sliding.shouldPresent(slidingCardContent, from: self) + + + } + +} diff --git a/Demo/Demo/ViewControllers/HighlightViewController.swift b/Demo/Demo/ViewControllers/HighlightViewController.swift new file mode 100644 index 0000000..8dc3db1 --- /dev/null +++ b/Demo/Demo/ViewControllers/HighlightViewController.swift @@ -0,0 +1,64 @@ +// +// HighlightViewController.swift +// Demo +// +// Created by Paolo Cuscela on 30/10/17. +// Copyright © 2017 Paolo Cuscela. All rights reserved. +// + +import UIKit +import Cards +import Foundation + +class HighlightViewController: UIViewController { + + @IBOutlet weak var first: CardHighlight! + @IBOutlet weak var second: CardHighlight! + + let colors = [ + + UIColor.red, + UIColor.yellow, + UIColor.blue, + UIColor.green, + UIColor.gray, + UIColor.brown, + UIColor.purple, + UIColor.orange + + ] + + override func viewDidLoad() { + super.viewDidLoad() + + first.delegate = self + first.hasParallax = true + + second.delegate = self + let cardContent = storyboard?.instantiateViewController(withIdentifier: "CardContent").view + second.shouldPresent(cardContent, from: self) + + + } + + +} + + +extension HighlightViewController: CardDelegate { + + func cardDidTapInside(card: Card) { + + if card == first { + card.shadowColor = colors[Int(arc4random_uniform(UInt32(colors.count)))] + } else { + print("Hey, I'm the second one :)") + } + } + + func cardHighlightDidTapButton(card: CardHighlight, button: UIButton) { + + card.buttonText = "HEY!" + } + +} diff --git a/Demo/Demo/ViewControllers/PlayerViewController.swift b/Demo/Demo/ViewControllers/PlayerViewController.swift new file mode 100644 index 0000000..1f65d82 --- /dev/null +++ b/Demo/Demo/ViewControllers/PlayerViewController.swift @@ -0,0 +1,38 @@ +// +// PlayerViewController.swift +// Demo +// +// Created by Paolo Cuscela on 30/10/17. +// Copyright © 2017 Paolo Cuscela. All rights reserved. +// + +import UIKit +import Cards + +class PlayerViewController: UIViewController { + + @IBOutlet weak var card: CardPlayer! + + override func viewDidLoad() { + super.viewDidLoad() + + card.videoSource = URL(string: "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") + card.shouldDisplayPlayer(from: self) //Required. + + card.playerCover = UIImage(named: "mvBackground")! // Shows while the player is loading + card.playImage = UIImage(named: "CardPlayerPlayIcon")! // Play button icon + + card.isAutoplayEnabled = false + card.shouldRestartVideoWhenPlaybackEnds = true + + card.title = "Big Buck Bunny" + card.subtitle = "Inside the extraordinary world of Buck Bunny" + card.category = "today's movie" + + let cardContent = storyboard?.instantiateViewController(withIdentifier: "CardContent").view + card.shouldPresent(cardContent, from: self) + + } + + +} diff --git a/README.md b/README.md index 6f39743..4d5d9e6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ![Overview](https://raw.githubusercontent.com/PaoloCuscela/Cards/master/Images/Header.png) -

Cards brings to XCode the card views you can see in the new iOS XI Appstore.

+

Cards brings to XCode the card views seen in the new iOS XI Appstore.

## Getting Started @@ -106,7 +106,7 @@ var blurEffect: UIBlurEffectStyle //Blur effect of CardGroup let card = CardPlayer(frame: CGRect(x: 40, y: 50, width: 300 , height: 360)) card.textColor = UIColor.black card.videoSource = URL(string: "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4") -self.addChildViewController(card.player) /// IMPORTANT: Don't forget this +card.shouldDisplayPlayer(from: self) //Required. card.playerCover = UIImage(named: "mvBackground")! // Shows while the player is loading card.playImage = UIImage(named: "CardPlayerPlayIcon")! // Play button icon