ActionSheetDefaultPresenter.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //
  2. // ActionSheetDefaultPresenter.swift
  3. // Sheeeeeeeeet
  4. //
  5. // Created by Daniel Saidi on 2017-11-27.
  6. // Copyright © 2017 Daniel Saidi. All rights reserved.
  7. //
  8. /*
  9. This presenter will present action sheets as regular action
  10. sheets, which means that it presents sheets from the bottom.
  11. */
  12. import UIKit
  13. open class ActionSheetDefaultPresenter: ActionSheetPresenter {
  14. // MARK: - Initialization
  15. public init() {}
  16. deinit { print("\(type(of: self)) deinit") }
  17. // MARK: - Properties
  18. open var availablePresentationSize: CGSize { return UIScreen.main.bounds.size }
  19. open var events = ActionSheetPresenterEvents()
  20. open var isDismissableWithTapOnBackground = true
  21. private var actionSheet: ActionSheet?
  22. private var actionSheetView: UIView?
  23. private var backgroundColor = UIColor.black.withAlphaComponent(0.4)
  24. private var backgroundView: UIView?
  25. // MARK: - ActionSheetPresenter
  26. open func dismiss(completion: @escaping () -> ()) {
  27. dismissActionSheet()
  28. completion()
  29. }
  30. open func present(sheet: ActionSheet, in vc: UIViewController, from view: UIView?) {
  31. present(sheet: sheet, in: vc)
  32. }
  33. open func present(sheet: ActionSheet, in vc: UIViewController, from item: UIBarButtonItem) {
  34. present(sheet: sheet, in: vc)
  35. }
  36. open func present(sheet: ActionSheet, in vc: UIViewController) {
  37. actionSheet = sheet
  38. addBackgroundView(to: vc.view)
  39. addActionSheetView(from: sheet, to: vc.view)
  40. presentBackgroundView()
  41. presentActionSheet(sheet, in: vc.view)
  42. }
  43. // MARK: - Protected, overridable Functions
  44. open func addActionSheetView(from sheet: ActionSheet, to view: UIView) {
  45. guard let sheetView = sheet.view else { return }
  46. sheetView.frame.size.height = sheet.contentHeight
  47. view.addSubview(sheetView)
  48. actionSheetView = sheetView
  49. }
  50. open func addBackgroundView(to view: UIView) {
  51. let bgView = UIView(frame: view.frame)
  52. bgView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  53. addBackgroundViewTapAction(to: bgView)
  54. view.addSubview(bgView)
  55. bgView.backgroundColor = backgroundColor
  56. backgroundView = bgView
  57. }
  58. open func addBackgroundViewTapAction(to view: UIView) {
  59. view.isUserInteractionEnabled = true
  60. let action = #selector(backgroundViewTapAction)
  61. let tap = UITapGestureRecognizer(target: self, action: action)
  62. view.addGestureRecognizer(tap)
  63. }
  64. open func animate(_ animation: @escaping () -> ()) {
  65. animate(animation, completion: nil)
  66. }
  67. open func animate(_ animation: @escaping () -> (), completion: (() -> ())?) {
  68. UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: animation) { _ in completion?() }
  69. }
  70. open func dismissActionSheet() {
  71. actionSheet = nil
  72. removeActionSheetView()
  73. removeBackgroundView()
  74. }
  75. open func presentActionSheet(_ sheet: ActionSheet, in view: UIView) {
  76. guard let sheetView = actionSheetView else { return }
  77. sheetView.frame = presentationTransitionStartFrame(for: sheet, in: view)
  78. animate { sheetView.frame = self.presentationFrame(for: sheet, in: view) ?? .zero }
  79. sheetView.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
  80. }
  81. open func presentationFrame(for sheet: ActionSheet, in view: UIView) -> CGRect? {
  82. return sheet.bottomPresentationFrame
  83. }
  84. open func presentationTransitionStartFrame(for sheet: ActionSheet, in view: UIView) -> CGRect {
  85. var frame = presentationFrame(for: sheet, in: view) ?? .zero
  86. frame.origin.y += 100
  87. return frame
  88. }
  89. open func presentBackgroundView() {
  90. guard let view = backgroundView else { return }
  91. view.alpha = 0
  92. animate { view.alpha = 1 }
  93. }
  94. open func removeActionSheetView() {
  95. guard let view = actionSheetView else { return }
  96. var frame = view.frame
  97. frame.origin.y += frame.height + 100
  98. let animation = { view.frame = frame }
  99. animate(animation) { view.removeFromSuperview() }
  100. }
  101. open func removeBackgroundView() {
  102. guard let view = backgroundView else { return }
  103. let animation = { view.alpha = 0 }
  104. animate(animation) { view.removeFromSuperview() }
  105. }
  106. }
  107. // MARK: - Actions
  108. @objc public extension ActionSheetDefaultPresenter {
  109. public func backgroundViewTapAction() {
  110. guard isDismissableWithTapOnBackground else { return }
  111. events.didDismissWithBackgroundTap?()
  112. dismissActionSheet()
  113. }
  114. }