Compare commits

..

2 Commits

Author SHA1 Message Date
Ivan Vorobei 8348cd6396 Update to 1.7.2
Fix bugs with events delegate.
2019-07-11 01:17:48 +03:00
Ivan Vorobei 9f4c1be56d Update to 1.7.1
Add confirmation to dismiss by scroll. Change `SPStorkControllerConfirmDelegate` to required methods. Update example.
2019-07-10 21:46:53 +03:00
12 changed files with 169 additions and 91 deletions
@@ -39,6 +39,7 @@ class Controller: UIViewController {
let modal = ModalTableViewController()
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.storkDelegate = self
transitionDelegate.confirmDelegate = modal
modal.transitioningDelegate = transitionDelegate
modal.modalPresentationStyle = .custom
self.present(modal, animated: true, completion: nil)
@@ -23,7 +23,7 @@ import UIKit
@objc public protocol SPStorkControllerConfirmDelegate: class {
@objc optional var needConfirm: Bool { get }
var needConfirm: Bool { get }
@objc optional func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
}
@@ -32,14 +32,10 @@ public enum SPStorkController {
scrollView.subviews.forEach {
$0.transform = CGAffineTransform(translationX: 0, y: -translation)
}
/* Maybe migrate to it in future. Bug with bottom safe area
scrollView.transform = CGAffineTransform(translationX: 0, y: -translation)
scrollView.scrollIndicatorInsets.top = (indicatorInset ?? 0) + translation
*/
presentationController.setIndicator(style: scrollView.isTracking ? .line : .arrow)
if translation >= presentationController.translateForDismiss * 0.4 {
if !scrollView.isTracking && !scrollView.isDragging {
presentationController.presentedViewController.dismiss(animated: true, completion: {
presentationController.dismissWithConfirmation(prepare: nil, completion: {
presentationController.storkDelegate?.didDismissStorkBySwipe?()
})
return
@@ -51,6 +51,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
private var snapshotViewWidthConstraint: NSLayoutConstraint?
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
var workConfirmation: Bool = false
private var workGester: Bool = false
private var startDismissing: Bool = false
private var afterReleaseDismissing: Bool = false
@@ -69,7 +70,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
return factor
}
private var feedbackGenerator: UIImpactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
private var feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
override var presentedView: UIView? {
let view = self.presentedViewController.view
@@ -106,7 +107,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
if self.showIndicator {
self.indicatorView.color = self.indicatorColor
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapIndicator))
tap.cancelsTouchesInView = false
self.indicatorView.addGestureRecognizer(tap)
presentedView.addSubview(self.indicatorView)
@@ -121,7 +122,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.gradeView.alpha = 0
if self.showCloseButton {
self.closeButton.addTarget(self, action: #selector(self.dismissAction), for: .touchUpInside)
self.closeButton.addTarget(self, action: #selector(self.tapCloseButton), for: .touchUpInside)
presentedView.addSubview(self.closeButton)
}
self.updateLayoutCloseButton()
@@ -208,7 +209,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.updateSnapshotAspectRatio()
if self.tapAroundToDismissEnabled {
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapArround))
self.tap?.cancelsTouchesInView = false
self.snapshotViewContainer.addGestureRecognizer(self.tap!)
}
@@ -222,21 +223,13 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
}
}
@objc func dismissAction() {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
override func dismissalTransitionWillBegin() {
super.dismissalTransitionWillBegin()
guard let containerView = containerView else { return }
self.startDismissing = true
let initialFrame: CGRect = presentingViewController.isPresentedAsStork ? presentingViewController.view.frame : containerView.bounds
let initialTransform = CGAffineTransform.identity
.translatedBy(x: 0, y: -initialFrame.origin.y)
.translatedBy(x: 0, y: self.topSpace)
@@ -313,6 +306,56 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
extension SPStorkPresentationController {
@objc func tapIndicator() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
@objc func tapArround() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
@objc func tapCloseButton() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
public func dismissWithConfirmation(prepare: (()->())?, completion: (()->())?) {
let dismiss = {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: {
completion?()
})
}
guard let confirmDelegate = self.confirmDelegate else {
dismiss()
return
}
if self.workConfirmation { return }
if confirmDelegate.needConfirm {
prepare?()
self.workConfirmation = true
confirmDelegate.confirm({ (isConfirmed) in
self.workConfirmation = false
self.afterReleaseDismissing = false
if isConfirmed {
dismiss()
}
})
} else {
dismiss()
}
}
@objc func handlePan(gestureRecognizer: UIPanGestureRecognizer) {
guard gestureRecognizer.isEqual(self.pan), self.swipeToDismissEnabled else { return }
@@ -336,7 +379,7 @@ extension SPStorkPresentationController {
self.workGester = false
let translation = gestureRecognizer.translation(in: presentedView).y
let returnToDefault = {
let toDefault = {
self.indicatorView.style = .arrow
UIView.animate(
withDuration: 0.6,
@@ -351,25 +394,12 @@ extension SPStorkPresentationController {
})
}
let dismissBySwipe = {
self.presentedViewController.dismiss(animated: true, completion: {
if translation >= self.translateForDismiss {
self.dismissWithConfirmation(prepare: toDefault, completion: {
self.storkDelegate?.didDismissStorkBySwipe?()
})
}
if translation >= self.translateForDismiss {
if self.confirmDelegate?.needConfirm ?? false {
returnToDefault()
self.confirmDelegate?.confirm?({ (isConfirmed) in
if isConfirmed {
dismissBySwipe()
}
})
} else {
dismissBySwipe()
}
} else {
returnToDefault()
toDefault()
}
default:
break
@@ -420,7 +450,7 @@ extension SPStorkPresentationController {
let elasticThreshold: CGFloat = 120
let translationFactor: CGFloat = 1 / 2
if translation >= 0 {
let translationForModal: CGFloat = {
if translation >= elasticThreshold {
@@ -446,8 +476,10 @@ extension SPStorkPresentationController {
let afterRealseDismissing = (translation >= self.translateForDismiss)
if afterRealseDismissing != self.afterReleaseDismissing {
self.afterReleaseDismissing = afterRealseDismissing
if self.hapticMoments.contains(.willDismissIfRelease) {
self.feedbackGenerator.impactOccurred()
if !self.workConfirmation {
if self.hapticMoments.contains(.willDismissIfRelease) {
self.feedbackGenerator.impactOccurred()
}
}
}
}
@@ -479,8 +511,6 @@ extension SPStorkPresentationController {
private func updateLayoutIndicator() {
self.indicatorView.style = .line
self.indicatorView.sizeToFit()
//self.indicatorView.frame.origin.y = 12
//self.indicatorView.center.x = presentedView.frame.width / 2
}
private func updateLayoutCloseButton() {
@@ -49,7 +49,11 @@ class ModalTableViewController: UIViewController {
}
@objc func dismissAction() {
self.dismiss()
if let storkPresentationController = self.presentationController as? SPStorkPresentationController {
storkPresentationController.dismissWithConfirmation(prepare: nil, completion: {
print("Custom completion for confirmation. Confirmation is optional.")
})
}
}
}
@@ -79,3 +83,20 @@ extension ModalTableViewController: UITableViewDelegate {
}
}
extension ModalTableViewController: SPStorkControllerConfirmDelegate {
var needConfirm: Bool {
return true
}
func confirm(_ completion: @escaping (Bool) -> ()) {
let alertController = UIAlertController(title: "Need dismiss?", message: "It test confirm option for SPStorkController", preferredStyle: .actionSheet)
alertController.addDestructiveAction(title: "Confirm", complection: {
completion(true)
})
alertController.addCancelAction(title: "Cancel") {
completion(false)
}
self.present(alertController)
}
}
@@ -20,7 +20,11 @@ class ModalViewController: UIViewController {
}
@objc func dismissAction() {
self.dismiss()
if let storkPresentationController = self.presentationController as? SPStorkPresentationController {
storkPresentationController.dismissWithConfirmation(prepare: nil, completion: {
print("Custom completion for confirmation. Confirmation is optional.")
})
}
}
override func viewWillAppear(_ animated: Bool) {
@@ -35,12 +39,12 @@ class ModalViewController: UIViewController {
extension ModalViewController: SPStorkControllerConfirmDelegate {
var needConfirm: Bool {
return false
return true
}
func confirm(_ completion: @escaping (Bool) -> ()) {
let alertController = UIAlertController(title: "Need dismiss?", message: "It test confirm option for SPStorkController", preferredStyle: .actionSheet)
alertController.addAction(title: "Confirm", complection: {
alertController.addDestructiveAction(title: "Confirm", complection: {
completion(true)
})
alertController.addCancelAction(title: "Cancel") {
+2 -2
View File
@@ -282,9 +282,9 @@ For confirm closing by swipe, use `SPStorkControllerConfirmDelegate`. Implenet p
```swift
@objc public protocol SPStorkControllerConfirmDelegate: class {
@objc optional var needConfirm: Bool { get }
var needConfirm: Bool { get }
@objc optional func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
}
```
+1 -1
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "SPStorkController"
s.version = "1.7"
s.version = "1.7.2"
s.summary = "Very similar to the controllers displayed in Apple Music, Podcasts and Mail Apple's applications."
s.homepage = "https://github.com/IvanVorobei/SPStorkController"
s.source = { :git => "https://github.com/IvanVorobei/SPStorkController.git", :tag => s.version }
@@ -23,7 +23,7 @@ import UIKit
@objc public protocol SPStorkControllerConfirmDelegate: class {
@objc optional var needConfirm: Bool { get }
var needConfirm: Bool { get }
@objc optional func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
}
@@ -32,14 +32,10 @@ public enum SPStorkController {
scrollView.subviews.forEach {
$0.transform = CGAffineTransform(translationX: 0, y: -translation)
}
/* Maybe migrate to it in future. Bug with bottom safe area
scrollView.transform = CGAffineTransform(translationX: 0, y: -translation)
scrollView.scrollIndicatorInsets.top = (indicatorInset ?? 0) + translation
*/
presentationController.setIndicator(style: scrollView.isTracking ? .line : .arrow)
if translation >= presentationController.translateForDismiss * 0.4 {
if !scrollView.isTracking && !scrollView.isDragging {
presentationController.presentedViewController.dismiss(animated: true, completion: {
presentationController.dismissWithConfirmation(prepare: nil, completion: {
presentationController.storkDelegate?.didDismissStorkBySwipe?()
})
return
@@ -51,6 +51,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
private var snapshotViewWidthConstraint: NSLayoutConstraint?
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
var workConfirmation: Bool = false
private var workGester: Bool = false
private var startDismissing: Bool = false
private var afterReleaseDismissing: Bool = false
@@ -69,7 +70,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
return factor
}
private var feedbackGenerator: UIImpactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
private var feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
override var presentedView: UIView? {
let view = self.presentedViewController.view
@@ -106,7 +107,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
if self.showIndicator {
self.indicatorView.color = self.indicatorColor
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapIndicator))
tap.cancelsTouchesInView = false
self.indicatorView.addGestureRecognizer(tap)
presentedView.addSubview(self.indicatorView)
@@ -121,7 +122,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.gradeView.alpha = 0
if self.showCloseButton {
self.closeButton.addTarget(self, action: #selector(self.dismissAction), for: .touchUpInside)
self.closeButton.addTarget(self, action: #selector(self.tapCloseButton), for: .touchUpInside)
presentedView.addSubview(self.closeButton)
}
self.updateLayoutCloseButton()
@@ -208,7 +209,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.updateSnapshotAspectRatio()
if self.tapAroundToDismissEnabled {
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapArround))
self.tap?.cancelsTouchesInView = false
self.snapshotViewContainer.addGestureRecognizer(self.tap!)
}
@@ -222,21 +223,13 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
}
}
@objc func dismissAction() {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
override func dismissalTransitionWillBegin() {
super.dismissalTransitionWillBegin()
guard let containerView = containerView else { return }
self.startDismissing = true
let initialFrame: CGRect = presentingViewController.isPresentedAsStork ? presentingViewController.view.frame : containerView.bounds
let initialTransform = CGAffineTransform.identity
.translatedBy(x: 0, y: -initialFrame.origin.y)
.translatedBy(x: 0, y: self.topSpace)
@@ -313,6 +306,56 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
extension SPStorkPresentationController {
@objc func tapIndicator() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
@objc func tapArround() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
@objc func tapCloseButton() {
self.dismissWithConfirmation(prepare: nil, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
public func dismissWithConfirmation(prepare: (()->())?, completion: (()->())?) {
let dismiss = {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: {
completion?()
})
}
guard let confirmDelegate = self.confirmDelegate else {
dismiss()
return
}
if self.workConfirmation { return }
if confirmDelegate.needConfirm {
prepare?()
self.workConfirmation = true
confirmDelegate.confirm({ (isConfirmed) in
self.workConfirmation = false
self.afterReleaseDismissing = false
if isConfirmed {
dismiss()
}
})
} else {
dismiss()
}
}
@objc func handlePan(gestureRecognizer: UIPanGestureRecognizer) {
guard gestureRecognizer.isEqual(self.pan), self.swipeToDismissEnabled else { return }
@@ -336,7 +379,7 @@ extension SPStorkPresentationController {
self.workGester = false
let translation = gestureRecognizer.translation(in: presentedView).y
let returnToDefault = {
let toDefault = {
self.indicatorView.style = .arrow
UIView.animate(
withDuration: 0.6,
@@ -351,25 +394,12 @@ extension SPStorkPresentationController {
})
}
let dismissBySwipe = {
self.presentedViewController.dismiss(animated: true, completion: {
if translation >= self.translateForDismiss {
self.dismissWithConfirmation(prepare: toDefault, completion: {
self.storkDelegate?.didDismissStorkBySwipe?()
})
}
if translation >= self.translateForDismiss {
if self.confirmDelegate?.needConfirm ?? false {
returnToDefault()
self.confirmDelegate?.confirm?({ (isConfirmed) in
if isConfirmed {
dismissBySwipe()
}
})
} else {
dismissBySwipe()
}
} else {
returnToDefault()
toDefault()
}
default:
break
@@ -420,7 +450,7 @@ extension SPStorkPresentationController {
let elasticThreshold: CGFloat = 120
let translationFactor: CGFloat = 1 / 2
if translation >= 0 {
let translationForModal: CGFloat = {
if translation >= elasticThreshold {
@@ -446,8 +476,10 @@ extension SPStorkPresentationController {
let afterRealseDismissing = (translation >= self.translateForDismiss)
if afterRealseDismissing != self.afterReleaseDismissing {
self.afterReleaseDismissing = afterRealseDismissing
if self.hapticMoments.contains(.willDismissIfRelease) {
self.feedbackGenerator.impactOccurred()
if !self.workConfirmation {
if self.hapticMoments.contains(.willDismissIfRelease) {
self.feedbackGenerator.impactOccurred()
}
}
}
}
@@ -479,8 +511,6 @@ extension SPStorkPresentationController {
private func updateLayoutIndicator() {
self.indicatorView.style = .line
self.indicatorView.sizeToFit()
//self.indicatorView.frame.origin.y = 12
//self.indicatorView.center.x = presentedView.frame.width / 2
}
private func updateLayoutCloseButton() {