No Description

ActionSheetView.swift 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // ActionSheetView.swift
  3. // PaiaiUIKit
  4. //
  5. // Created by FFIB on 2017/11/17.
  6. // Copyright © 2017年 FFIB. All rights reserved.
  7. //
  8. import UIKit
  9. public final class ActionSheetView: UIView {
  10. public static var `default`: ActionSheetView {
  11. return ActionSheetView()
  12. }
  13. private typealias ButtonAction = ((AlertAction) -> Void)
  14. public private(set) var alertActions: [AlertAction] = []
  15. public private(set) var cancelAction: AlertAction? = nil
  16. private var _cancelItem: AlertItem?
  17. private var _alertItems: [AlertItem] = []
  18. private var actions: [ButtonAction] = []
  19. private var viewNotReady = true
  20. var title: String = ""
  21. var message: String = ""
  22. override public func didMoveToWindow() {
  23. super.didMoveToWindow()
  24. guard viewNotReady else { return }
  25. constructViewHierarchy()
  26. activateConstraints()
  27. installTarget()
  28. backgroundColor = UIColor(r: 153, g: 153, b: 153)
  29. viewNotReady = false
  30. }
  31. private func constructViewHierarchy() {
  32. for item in _alertItems { addSubview(item) }
  33. guard let item = _cancelItem else { return }
  34. addSubview(item)
  35. }
  36. private func activateConstraints() {
  37. activateConstraintsCancelItem()
  38. activateConstraintsItems()
  39. activateConstraintsRootView()
  40. }
  41. func addAlertAction(_ action: AlertAction) {
  42. switch action.style {
  43. case .default, .custom:
  44. alertActions.append(action)
  45. _alertItems.append(action.style.item)
  46. case .cancel:
  47. cancelAction = action
  48. _cancelItem = action.style.item
  49. }
  50. }
  51. private func installTarget() {
  52. if cancelAction != nil {
  53. _cancelItem?.addTarget(self, action: #selector(cancelAction(btn:)), for: .touchUpInside)
  54. }
  55. for (i, item) in _alertItems.enumerated() {
  56. item.sign = i
  57. item.addTarget(self, action: #selector(alertAction), for: .touchUpInside)
  58. }
  59. }
  60. @objc private func alertAction(btn: UIButton) {
  61. guard let alertItem = btn as? AlertItem else { return }
  62. alertActions[alertItem.sign].handler?(alertItem)
  63. dismissSuperViewController()
  64. }
  65. @objc private func cancelAction(btn: UIButton) {
  66. guard let cancelItem = _cancelItem else { return }
  67. cancelAction?.handler?(cancelItem)
  68. dismissSuperViewController()
  69. }
  70. private func dismissSuperViewController() {
  71. guard let vc = getSuperViewController() else { return }
  72. vc.dismissController()
  73. }
  74. }
  75. /// MARK:
  76. fileprivate extension ActionSheetView {
  77. func activateConstraintsRootView() {
  78. guard let v = superview else { return }
  79. translatesAutoresizingMaskIntoConstraints = false
  80. NSLayoutConstraint.activate([
  81. bottomAnchor.constraint(equalTo: v.bottomAnchor),
  82. leadingAnchor.constraint(equalTo: v.leadingAnchor),
  83. trailingAnchor.constraint(equalTo: v.trailingAnchor)
  84. ])
  85. }
  86. func activateConstraintsCancelItem() {
  87. guard let alertAction = cancelAction,
  88. let cancelItem = _cancelItem else { return }
  89. cancelItem.translatesAutoresizingMaskIntoConstraints = false
  90. cancelItem.setTitle(alertAction.title, for: .normal)
  91. NSLayoutConstraint.activate([
  92. cancelItem.heightAnchor.constraint(equalToConstant: 44),
  93. cancelItem.leadingAnchor.constraint(equalTo: leadingAnchor),
  94. cancelItem.trailingAnchor.constraint(equalTo: trailingAnchor),
  95. cancelItem.bottomAnchor.constraint(equalTo: bottomAnchor)
  96. ])
  97. }
  98. func activateConstraintsItems() {
  99. guard !alertActions.isEmpty else { return }
  100. var last: UIButton? = _cancelItem
  101. var bottom: CGFloat = _cancelItem == nil ? 0 : -6
  102. for (alertAction, item) in zip(alertActions, _alertItems).reversed() {
  103. item.translatesAutoresizingMaskIntoConstraints = false
  104. item.setTitle(alertAction.title, for: .normal)
  105. NSLayoutConstraint.activate([
  106. item.heightAnchor.constraint(equalToConstant: 44),
  107. item.leadingAnchor.constraint(equalTo: leadingAnchor),
  108. item.trailingAnchor.constraint(equalTo: trailingAnchor),
  109. item.bottomAnchor.constraint(equalTo: last?.topAnchor ?? bottomAnchor, constant: bottom)
  110. ])
  111. last = item
  112. bottom = -1
  113. }
  114. NSLayoutConstraint.activate([topAnchor.constraint(equalTo: last!.topAnchor)])
  115. }
  116. }
  117. fileprivate extension AlertAction.Style {
  118. var item: AlertItem {
  119. switch self {
  120. case .cancel:
  121. return BottomCancelItem()
  122. case .default:
  123. return BottomDefaultItem()
  124. case let .custom(v):
  125. return v
  126. }
  127. }
  128. }