Presentr.swift 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //
  2. // Presentr.swift
  3. // Presentr
  4. //
  5. // Created by Daniel Lozano on 5/10/16.
  6. // Copyright © 2016 Icalia Labs. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. public enum PresentrConstants {
  11. public enum Values {
  12. public static let defaultSideMargin: Float = 30.0
  13. public static let defaultHeightPercentage: Float = 0.66
  14. }
  15. public enum Strings {
  16. public static let alertTitle = "Alert"
  17. public static let alertBody = "This is an alert."
  18. }
  19. }
  20. public enum DismissSwipeDirection {
  21. case `default`
  22. case bottom
  23. case top
  24. }
  25. // MARK: - PresentrDelegate
  26. /**
  27. The 'PresentrDelegate' protocol defines methods that you use to respond to changes from the 'PresentrController'. All of the methods of this protocol are optional.
  28. */
  29. @objc public protocol PresentrDelegate {
  30. /**
  31. Asks the delegate if it should dismiss the presented controller on the tap of the outer chrome view.
  32. Use this method to validate requirments or finish tasks before the dismissal of the presented controller.
  33. After things are wrapped up and verified it may be good to dismiss the presented controller automatically so the user does't have to close it again.
  34. - parameter keyboardShowing: Whether or not the keyboard is currently being shown by the presented view.
  35. - returns: False if the dismissal should be prevented, otherwise, true if the dimissal should occur.
  36. */
  37. @objc optional func presentrShouldDismiss(keyboardShowing: Bool) -> Bool
  38. }
  39. /// Main Presentr class. This is the point of entry for using the framework.
  40. public class Presentr: NSObject {
  41. /// This must be set during initialization, but can be changed to reuse a Presentr object.
  42. public var presentationType: PresentationType
  43. /// The type of transition animation to be used to present the view controller. This is optional, if not provided the default for each presentation type will be used.
  44. public var transitionType: TransitionType?
  45. /// The type of transition animation to be used to dismiss the view controller. This is optional, if not provided transitionType or default value will be used.
  46. public var dismissTransitionType: TransitionType?
  47. /// Should the presented controller have rounded corners. Each presentation type has its own default if nil.
  48. public var roundCorners: Bool?
  49. /// Radius of rounded corners for presented controller if roundCorners is true. Default is 4.
  50. public var cornerRadius: CGFloat = 20
  51. /// Shadow settings for presented controller.
  52. public var dropShadow: PresentrShadow?
  53. /// Should the presented controller dismiss on background tap. Default is true.
  54. public var dismissOnTap = true
  55. /// Should the presented controller dismiss on Swipe inside the presented view controller. Default is false.
  56. public var dismissOnSwipe = false
  57. /// If dismissOnSwipe is true, the direction for the swipe. Default depends on presentation type.
  58. public var dismissOnSwipeDirection: DismissSwipeDirection = .default
  59. /// Should the presented controller use animation when dismiss on background tap or swipe. Default is true.
  60. public var dismissAnimated = true
  61. /// Color of the background. Default is Black.
  62. public var backgroundColor = UIColor.black
  63. /// Opacity of the background. Default is 0.7.
  64. public var backgroundOpacity: Float = 0.7
  65. /// Should the presented controller blur the background. Default is false.
  66. public var blurBackground = false
  67. /// The type of blur to be applied to the background. Ignored if blurBackground is set to false. Default is Dark.
  68. public var blurStyle: UIBlurEffect.Style = .dark
  69. /// A custom background view to be added on top of the regular background view.
  70. public var customBackgroundView: UIView?
  71. /// How the presented view controller should respond to keyboard presentation.
  72. public var keyboardTranslationType: KeyboardTranslationType = .none
  73. /// When a ViewController for context is set this handles what happens to a tap when it is outside the context. True will ignore tap and pass the tap to the background controller, false will handle the tap and dismiss the presented controller. Default is false.
  74. public var shouldIgnoreTapOutsideContext = false
  75. /// Uses the ViewController's frame as context for the presentation. Imitates UIModalPresentation.currentContext
  76. public weak var viewControllerForContext: UIViewController? {
  77. didSet {
  78. guard let viewController = viewControllerForContext, let view = viewController.view else {
  79. contextFrameForPresentation = nil
  80. return
  81. }
  82. let correctedOrigin = view.convert(view.frame.origin, to: nil) // Correct origin in relation to UIWindow
  83. contextFrameForPresentation = CGRect(x: correctedOrigin.x, y: correctedOrigin.y, width: view.bounds.width, height: view.bounds.height)
  84. }
  85. }
  86. fileprivate var contextFrameForPresentation: CGRect?
  87. // MARK: Init
  88. public init(presentationType: PresentationType) {
  89. self.presentationType = presentationType
  90. }
  91. // MARK: Class Helper Methods
  92. /**
  93. Public helper class method for creating and configuring an instance of the 'AlertViewController'
  94. - parameter title: Title to be used in the Alert View Controller.
  95. - parameter body: Body of the message to be displayed in the Alert View Controller.
  96. - returns: Returns a configured instance of 'AlertViewController'
  97. */
  98. static func alertViewController(title: String = PresentrConstants.Strings.alertTitle, body: String = PresentrConstants.Strings.alertBody) -> OOAlertViewController {
  99. let alertController = OOAlertViewController()
  100. alertController.titleText = title
  101. alertController.bodyText = body
  102. return alertController
  103. }
  104. // MARK: Private Methods
  105. /**
  106. Private method for presenting a view controller, using the custom presentation. Called from the UIViewController extension.
  107. - parameter presentingVC: The view controller which is doing the presenting.
  108. - parameter presentedVC: The view controller to be presented.
  109. - parameter animated: Animation boolean.
  110. - parameter completion: Completion block.
  111. */
  112. fileprivate func presentViewController(presentingViewController presentingVC: UIViewController, presentedViewController presentedVC: UIViewController, animated: Bool, completion: (() -> Void)?) {
  113. presentedVC.transitioningDelegate = self
  114. presentedVC.modalPresentationStyle = .custom
  115. presentingVC.present(presentedVC, animated: animated, completion: completion)
  116. }
  117. fileprivate var transitionForPresent: TransitionType {
  118. return transitionType ?? presentationType.defaultTransitionType()
  119. }
  120. fileprivate var transitionForDismiss: TransitionType {
  121. return dismissTransitionType ?? transitionType ?? presentationType.defaultTransitionType()
  122. }
  123. }
  124. // MARK: - UIViewControllerTransitioningDelegate
  125. extension Presentr: UIViewControllerTransitioningDelegate {
  126. public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
  127. return presentationController(presented, presenting: presenting)
  128. }
  129. public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  130. return transitionForPresent.animation()
  131. }
  132. public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  133. return transitionForDismiss.animation()
  134. }
  135. // MARK: - Private Helper's
  136. fileprivate func presentationController(_ presented: UIViewController, presenting: UIViewController?) -> PresentrController {
  137. return PresentrController(presentedViewController: presented,
  138. presentingViewController: presenting,
  139. presentationType: presentationType,
  140. roundCorners: roundCorners,
  141. cornerRadius: cornerRadius,
  142. dropShadow: dropShadow,
  143. dismissOnTap: dismissOnTap,
  144. dismissOnSwipe: dismissOnSwipe,
  145. dismissOnSwipeDirection: dismissOnSwipeDirection,
  146. backgroundColor: backgroundColor,
  147. backgroundOpacity: backgroundOpacity,
  148. blurBackground: blurBackground,
  149. blurStyle: blurStyle,
  150. customBackgroundView: customBackgroundView,
  151. keyboardTranslationType: keyboardTranslationType,
  152. dismissAnimated: dismissAnimated,
  153. contextFrameForPresentation: contextFrameForPresentation,
  154. shouldIgnoreTapOutsideContext: shouldIgnoreTapOutsideContext)
  155. }
  156. }
  157. // MARK: - UIViewController extension to provide customPresentViewController(_:viewController:animated:completion:) method
  158. public extension UIViewController {
  159. /// Present a view controller with a custom presentation provided by the Presentr object.
  160. ///
  161. /// - Parameters:
  162. /// - presentr: Presentr object used for custom presentation.
  163. /// - viewController: The view controller to be presented.
  164. /// - animated: Animation setting for the presentation.
  165. /// - completion: Completion handler.
  166. func customPresentViewController(_ presentr: Presentr, viewController: UIViewController, animated: Bool, completion: (() -> Void)?) {
  167. presentr.presentViewController(presentingViewController: self,
  168. presentedViewController: viewController,
  169. animated: animated,
  170. completion: completion)
  171. }
  172. }