Compare commits

..

13 Commits

Author SHA1 Message Date
Ivan Vorobei 64bebe0645 Update to 1.5.7
Add `closeButton` and parametres.
2019-03-25 15:42:10 +03:00
Ivan Vorobei 1efa55aefb Update to 1.5.6
Add events delegate
2019-03-24 18:57:27 +03:00
Ivan Vorobei e5371ca20c Update to 1.5.5
Add new parameter `hideIndicatorWhenScroll` - it allow shows and hide indicator when scrolling. Also fixed bug when invalid frame for dismissing action.
2019-03-24 13:23:08 +03:00
Ivan Vorobei fdbc1e3527 Update README.md 2019-03-23 23:28:22 +03:00
Ivan Vorobei 306547671c Update README.md 2019-03-23 19:46:22 +03:00
Ivan Vorobei 1fede9eb64 Update to 1.5.4
Fix bug with dublicate indicator
2019-03-07 11:34:01 +03:00
Ivan Vorobei 3ef2ff81bc Update README.md 2019-03-04 15:34:07 +03:00
Ivan Vorobei 83330bb509 Update to 1.5.2 2019-03-03 18:48:30 +03:00
Ivan Vorobei c4da6ff27e Update to 1.5.1
Add `cornerRadius` property.
2019-03-01 16:54:54 +03:00
Ivan Vorobei 686bbd749b Add scroll indicator inset 2019-02-24 16:42:54 +03:00
Ivan Vorobei 7b151fd268 Update to 1.5
Change interactive parapetres. Fix logic for dismiss controller by drag down on `UIScrollView`
2019-02-20 01:23:55 +03:00
Ivan Vorobei 7bdf702703 Update README.md 2019-02-19 20:07:37 +03:00
Ivan Vorobei 0d1381d941 Update to 1.4.8
Change logic for dismiss controller when scroll down in `UIScrollView`.
2019-02-19 20:01:53 +03:00
22 changed files with 450 additions and 108 deletions
@@ -7,17 +7,17 @@
objects = {
/* Begin PBXBuildFile section */
F40DB702222A9202004E1CCB /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB6FB222A9202004E1CCB /* SPStorkViewControllerExtenshion.swift */; };
F40DB703222A9202004E1CCB /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB6FC222A9202004E1CCB /* SPStorkTransitioningDelegate.swift */; };
F40DB704222A9202004E1CCB /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB6FD222A9202004E1CCB /* SPStorkPresentingAnimationController.swift */; };
F40DB705222A9202004E1CCB /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB6FE222A9202004E1CCB /* SPStorkPresentationController.swift */; };
F40DB706222A9202004E1CCB /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB6FF222A9202004E1CCB /* SPStorkController.swift */; };
F40DB707222A9202004E1CCB /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB700222A9202004E1CCB /* SPStorkIndicatorView.swift */; };
F40DB708222A9202004E1CCB /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40DB701222A9202004E1CCB /* SPStorkDismissingAnimationController.swift */; };
F445CA8721AED92600184254 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F445CA8621AED92600184254 /* AppDelegate.swift */; };
F445CA8921AED92600184254 /* Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = F445CA8821AED92600184254 /* Controller.swift */; };
F445CA8E21AED92700184254 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F445CA8D21AED92700184254 /* Assets.xcassets */; };
F445CA9121AED92700184254 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F445CA8F21AED92700184254 /* LaunchScreen.storyboard */; };
F4552722221C009D00F40446 /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267A221C009D00F40446 /* SPStorkViewControllerExtenshion.swift */; };
F4552723221C009D00F40446 /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267B221C009D00F40446 /* SPStorkTransitioningDelegate.swift */; };
F4552724221C009D00F40446 /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267C221C009D00F40446 /* SPStorkPresentingAnimationController.swift */; };
F4552725221C009D00F40446 /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267D221C009D00F40446 /* SPStorkPresentationController.swift */; };
F4552726221C009D00F40446 /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267E221C009D00F40446 /* SPStorkController.swift */; };
F4552727221C009D00F40446 /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F455267F221C009D00F40446 /* SPStorkIndicatorView.swift */; };
F4552728221C009D00F40446 /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4552680221C009D00F40446 /* SPStorkDismissingAnimationController.swift */; };
F4552729221C009D00F40446 /* SPVibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4552683221C009D00F40446 /* SPVibration.swift */; };
F455272A221C009D00F40446 /* SPPromoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4552687221C009D00F40446 /* SPPromoTableViewCell.swift */; };
F455272B221C009D00F40446 /* SPFormButtonTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4552689221C009D00F40446 /* SPFormButtonTableViewCell.swift */; };
@@ -141,19 +141,19 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
F40DB6FB222A9202004E1CCB /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
F40DB6FC222A9202004E1CCB /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
F40DB6FD222A9202004E1CCB /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
F40DB6FE222A9202004E1CCB /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
F40DB6FF222A9202004E1CCB /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
F40DB700222A9202004E1CCB /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
F40DB701222A9202004E1CCB /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
F445CA8321AED92600184254 /* stork-controller.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "stork-controller.app"; sourceTree = BUILT_PRODUCTS_DIR; };
F445CA8621AED92600184254 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F445CA8821AED92600184254 /* Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Controller.swift; sourceTree = "<group>"; };
F445CA8D21AED92700184254 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
F445CA9021AED92700184254 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
F445CA9221AED92700184254 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F455267A221C009D00F40446 /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
F455267B221C009D00F40446 /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
F455267C221C009D00F40446 /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
F455267D221C009D00F40446 /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
F455267E221C009D00F40446 /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
F455267F221C009D00F40446 /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
F4552680221C009D00F40446 /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
F4552683221C009D00F40446 /* SPVibration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPVibration.swift; sourceTree = "<group>"; };
F4552687221C009D00F40446 /* SPPromoTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPPromoTableViewCell.swift; sourceTree = "<group>"; };
F4552689221C009D00F40446 /* SPFormButtonTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPFormButtonTableViewCell.swift; sourceTree = "<group>"; };
@@ -287,6 +287,20 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
F40DB6FA222A9202004E1CCB /* SPStorkController */ = {
isa = PBXGroup;
children = (
F40DB6FB222A9202004E1CCB /* SPStorkViewControllerExtenshion.swift */,
F40DB6FC222A9202004E1CCB /* SPStorkTransitioningDelegate.swift */,
F40DB6FD222A9202004E1CCB /* SPStorkPresentingAnimationController.swift */,
F40DB6FE222A9202004E1CCB /* SPStorkPresentationController.swift */,
F40DB6FF222A9202004E1CCB /* SPStorkController.swift */,
F40DB700222A9202004E1CCB /* SPStorkIndicatorView.swift */,
F40DB701222A9202004E1CCB /* SPStorkDismissingAnimationController.swift */,
);
path = SPStorkController;
sourceTree = "<group>";
};
F445CA7A21AED92600184254 = {
isa = PBXGroup;
children = (
@@ -322,26 +336,12 @@
F445CA9821AED98500184254 /* Frameworks */ = {
isa = PBXGroup;
children = (
F40DB6FA222A9202004E1CCB /* SPStorkController */,
F4552681221C009D00F40446 /* SparrowKit */,
F4552679221C009D00F40446 /* SPStorkController */,
);
path = Frameworks;
sourceTree = "<group>";
};
F4552679221C009D00F40446 /* SPStorkController */ = {
isa = PBXGroup;
children = (
F455267A221C009D00F40446 /* SPStorkViewControllerExtenshion.swift */,
F455267B221C009D00F40446 /* SPStorkTransitioningDelegate.swift */,
F455267C221C009D00F40446 /* SPStorkPresentingAnimationController.swift */,
F455267D221C009D00F40446 /* SPStorkPresentationController.swift */,
F455267E221C009D00F40446 /* SPStorkController.swift */,
F455267F221C009D00F40446 /* SPStorkIndicatorView.swift */,
F4552680221C009D00F40446 /* SPStorkDismissingAnimationController.swift */,
);
path = SPStorkController;
sourceTree = "<group>";
};
F4552681221C009D00F40446 /* SparrowKit */ = {
isa = PBXGroup;
children = (
@@ -875,7 +875,6 @@
files = (
F455276B221C009E00F40446 /* SPArrayExtension.swift in Sources */,
F455276F221C009E00F40446 /* SPStrideableExtension.swift in Sources */,
F4552726221C009D00F40446 /* SPStorkController.swift in Sources */,
F4552729221C009D00F40446 /* SPVibration.swift in Sources */,
F4552760221C009E00F40446 /* SPCollectionView.swift in Sources */,
F4552744221C009E00F40446 /* SPFakeBarView.swift in Sources */,
@@ -883,9 +882,11 @@
F455277E221C009E00F40446 /* SPAppBadge.swift in Sources */,
F4552756221C009E00F40446 /* SPGolubevIconView.swift in Sources */,
F4552752221C009E00F40446 /* SPCenterLabelsView.swift in Sources */,
F40DB702222A9202004E1CCB /* SPStorkViewControllerExtenshion.swift in Sources */,
F4552776221C009E00F40446 /* SPUILabelExtenshion.swift in Sources */,
F445CA8921AED92600184254 /* Controller.swift in Sources */,
F4552775221C009E00F40446 /* SPCGRectExtension.swift in Sources */,
F40DB706222A9202004E1CCB /* SPStorkController.swift in Sources */,
F4552779221C009E00F40446 /* SPUIImageViewExtenshion.swift in Sources */,
F455278B221C009E00F40446 /* SPAnimationAlpha.swift in Sources */,
F455273A221C009E00F40446 /* SPAppleMusicSectionButtonsView.swift in Sources */,
@@ -899,7 +900,9 @@
F455273F221C009E00F40446 /* SPButton.swift in Sources */,
F4552759221C009E00F40446 /* SPTableController.swift in Sources */,
F4552786221C009E00F40446 /* SPLayout.swift in Sources */,
F40DB708222A9202004E1CCB /* SPStorkDismissingAnimationController.swift in Sources */,
F455279E221C009E00F40446 /* SPShare.swift in Sources */,
F40DB703222A9202004E1CCB /* SPStorkTransitioningDelegate.swift in Sources */,
F4552774221C009E00F40446 /* SPUINavigationControllerExtenshion.swift in Sources */,
F455275B221C009E00F40446 /* SPController.swift in Sources */,
F455279A221C009E00F40446 /* SPGolubevGolubevIconPack.swift in Sources */,
@@ -911,7 +914,6 @@
F4552749221C009E00F40446 /* SPDownloadingUIImageView.swift in Sources */,
F4552751221C009E00F40446 /* SPLabel.swift in Sources */,
F455276A221C009E00F40446 /* SPUIViewExtenshion.swift in Sources */,
F4552723221C009D00F40446 /* SPStorkTransitioningDelegate.swift in Sources */,
F4552794221C009E00F40446 /* SPAudio.swift in Sources */,
F455279C221C009E00F40446 /* SPRandom.swift in Sources */,
F4552778221C009E00F40446 /* SPCGSizeExtenshion.swift in Sources */,
@@ -923,6 +925,7 @@
F455276D221C009E00F40446 /* SPUIViewControllerExtenshion.swift in Sources */,
F4552736221C009D00F40446 /* SPTableViewCell.swift in Sources */,
F459D75D21C3ABBD00798524 /* ModalTableViewController.swift in Sources */,
F40DB705222A9202004E1CCB /* SPStorkPresentationController.swift in Sources */,
F4552798221C009E00F40446 /* SPCodeSystemIconPack.swift in Sources */,
F4552769221C009E00F40446 /* SPUITableView.swift in Sources */,
F455277A221C009E00F40446 /* SPUIColorExtension.swift in Sources */,
@@ -935,7 +938,6 @@
F455274C221C009E00F40446 /* SPSeparatorView.swift in Sources */,
F455273C221C009E00F40446 /* SPSystemIconButton.swift in Sources */,
F4552761221C009E00F40446 /* SPPageCollectionView.swift in Sources */,
F4552728221C009D00F40446 /* SPStorkDismissingAnimationController.swift in Sources */,
F4552767221C009E00F40446 /* SPUIFontExtenshion.swift in Sources */,
F4552766221C009E00F40446 /* SPUITextFieldExtenshion.swift in Sources */,
F4552772221C009E00F40446 /* SPTextFieldExtenshion.swift in Sources */,
@@ -945,7 +947,6 @@
F455272C221C009D00F40446 /* SPFormMailTableViewCell.swift in Sources */,
F4552773221C009E00F40446 /* SPUITabBarControllerExtenshion.swift in Sources */,
F4552737221C009E00F40446 /* SPTableView.swift in Sources */,
F4552724221C009D00F40446 /* SPStorkPresentingAnimationController.swift in Sources */,
F455278D221C009E00F40446 /* SPDownloader.swift in Sources */,
F4552777221C009E00F40446 /* SPDateExtenshion.swift in Sources */,
F4552782221C009E00F40446 /* SPLocalAuthentication.swift in Sources */,
@@ -954,17 +955,16 @@
F455275A221C009E00F40446 /* SPStatusBarManagerController.swift in Sources */,
F4552792221C009E00F40446 /* SPInstagram.swift in Sources */,
F455278F221C009E00F40446 /* SPTwitter.swift in Sources */,
F4552725221C009D00F40446 /* SPStorkPresentationController.swift in Sources */,
F455274B221C009E00F40446 /* SPGradientView.swift in Sources */,
F4552747221C009E00F40446 /* SPTextView.swift in Sources */,
F455275C221C009E00F40446 /* SPCollectionViewCell.swift in Sources */,
F40DB704222A9202004E1CCB /* SPStorkPresentingAnimationController.swift in Sources */,
F4552764221C009E00F40446 /* SPUIAlertControllerExtenshion.swift in Sources */,
F4552787221C009E00F40446 /* SPShadow.swift in Sources */,
F4552740221C009E00F40446 /* SPAppStoreActionButton.swift in Sources */,
F455275E221C009E00F40446 /* SPCollectionViewLayout.swift in Sources */,
F4552780221C009E00F40446 /* SPNativeColors.swift in Sources */,
F455272E221C009D00F40446 /* SPFormTextFiledTableViewCell.swift in Sources */,
F4552722221C009D00F40446 /* SPStorkViewControllerExtenshion.swift in Sources */,
F445CA8721AED92600184254 /* AppDelegate.swift in Sources */,
F4552738221C009E00F40446 /* SPPlayCircleButton.swift in Sources */,
F4552754221C009E00F40446 /* SPSocialIconView.swift in Sources */,
@@ -973,6 +973,7 @@
F459D75B21C3AB9A00798524 /* ModalViewController.swift in Sources */,
F4552771221C009E00F40446 /* SPUICollectionViewExtenshion.swift in Sources */,
F455277D221C009E00F40446 /* SPApp.swift in Sources */,
F40DB707222A9202004E1CCB /* SPStorkIndicatorView.swift in Sources */,
F455274E221C009E00F40446 /* SPBlurView.swift in Sources */,
F4552784221C009E00F40446 /* SPLocalNotification.swift in Sources */,
F4552757221C009E00F40446 /* SPProposeController.swift in Sources */,
@@ -981,7 +982,6 @@
F4552734221C009D00F40446 /* SPProposeTableViewCell.swift in Sources */,
F4552793221C009E00F40446 /* SPWhatsApp.swift in Sources */,
F4552788221C009E00F40446 /* SPShadowDeep.swift in Sources */,
F4552727221C009D00F40446 /* SPStorkIndicatorView.swift in Sources */,
F4552763221C009E00F40446 /* SPLocale.swift in Sources */,
F4552789221C009E00F40446 /* SPAnimationUpward.swift in Sources */,
F4552795221C009E00F40446 /* SPAudioPlayer.swift in Sources */,
+15 -7
View File
@@ -25,27 +25,35 @@ public struct SPStorkController {
static public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let controller = self.controller(for: scrollView) {
if let presentationController = controller.presentationController as? SPStorkPresentationController,
presentationController.swipeToDismissEnabled {
if let presentationController = controller.presentationController as? SPStorkPresentationController {
let translation = -(scrollView.contentOffset.y + scrollView.contentInset.top)
if translation >= 0 {
if controller.isBeingPresented { return }
scrollView.subviews.forEach {
$0.transform = CGAffineTransform(translationX: 0, y: -translation)
}
if let pan = presentationController.pan,
pan.state == .possible, pan.translation(in: controller.view).y <= 0 {
presentationController.scrollViewDidScroll(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: nil)
return
}
}
if presentationController.pan?.state != UIGestureRecognizer.State.changed {
presentationController.scrollViewDidScroll(translation * 2)
}
} else {
presentationController.setIndicator(style: .arrow)
presentationController.scrollViewDidScroll(0)
}
}
}
}
static var topScrollIndicatorInset: CGFloat {
return 6
}
static public func updatePresentingController(parent controller: UIViewController) {
if let presentationController = controller.presentedViewController?.presentationController as? SPStorkPresentationController {
presentationController.updatePresentingController()
@@ -28,7 +28,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
var showIndicator: Bool = true
var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
var customHeight: CGFloat? = nil
var translateForDismiss: CGFloat = 240
var translateForDismiss: CGFloat = 200
var transitioningDelegate: SPStorkTransitioningDelegate?
@@ -44,6 +44,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
private var snapshotViewTopConstraint: NSLayoutConstraint?
private var snapshotViewWidthConstraint: NSLayoutConstraint?
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
private var workGester: Bool = false
private var startDismissing: Bool = false
@@ -52,13 +53,8 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
return (statusBarHeight < 25) ? 30 : statusBarHeight
}
private var alpha: CGFloat {
return 0.51
}
private var cornerRadius: CGFloat {
return 10
}
private let alpha: CGFloat = 0.51
var cornerRadius: CGFloat = 10
private var scaleForPresentingView: CGFloat {
guard let containerView = containerView else { return 0 }
@@ -294,7 +290,7 @@ extension SPStorkPresentationController {
self.workGester = false
let translation = gestureRecognizer.translation(in: presentedView).y
if translation >= self.translateForDismiss {
presentedViewController.dismiss(animated: true, completion: nil)
self.presentedViewController.dismiss(animated: true, completion: nil)
} else {
self.indicatorView.style = .arrow
UIView.animate(
@@ -325,6 +321,10 @@ extension SPStorkPresentationController {
self.updateSnapshot()
}
func setIndicator(style: SPStorkIndicatorView.Style) {
self.indicatorView.style = style
}
private func updatePresentedViewForTranslation(inVerticalDirection translation: CGFloat) {
if self.startDismissing { return }
@@ -344,22 +344,18 @@ extension SPStorkPresentationController {
self.presentedView?.transform = CGAffineTransform(translationX: 0, y: translationForModal)
let factor = 1 + (translationForModal / 6000)
self.snapshotView?.transform = CGAffineTransform.init(scaleX: factor, y: factor)
self.gradeView.alpha = self.alpha - ((factor - 1) * 15)
let scaleFactor = 1 + (translationForModal / 5000)
self.snapshotView?.transform = CGAffineTransform.init(scaleX: scaleFactor, y: scaleFactor)
let gradeFactor = 1 + (translationForModal / 7000)
self.gradeView.alpha = self.alpha - ((gradeFactor - 1) * 15)
} else {
self.presentedView?.transform = CGAffineTransform.identity
}
}
}
extension SPStorkPresentationController {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if swipeToDismissEnabled, let scrollView = otherGestureRecognizer.view as? UIScrollView{
return scrollView.contentOffset.y <= 0
}
return false
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
guard let containerView = containerView else { return }
@@ -28,7 +28,8 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
public var showIndicator: Bool = true
public var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
public var customHeight: CGFloat? = nil
public var translateForDismiss: CGFloat = 240
public var translateForDismiss: CGFloat = 200
public var cornerRadius: CGFloat = 10
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
let controller = SPStorkPresentationController(presentedViewController: presented, presenting: presenting)
@@ -38,6 +39,7 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
controller.indicatorColor = self.indicatorColor
controller.customHeight = self.customHeight
controller.translateForDismiss = self.translateForDismiss
controller.cornerRadius = self.cornerRadius
controller.transitioningDelegate = self
return controller
}
@@ -29,9 +29,10 @@ extension UIViewController {
&& presentingViewController != nil
}
public func presentAsStork(_ controller: UIViewController, height: CGFloat? = nil, complection: (() -> Void)? = nil) {
public func presentAsStork(_ controller: UIViewController, height: CGFloat? = nil, showIndicator: Bool = false, complection: (() -> Void)? = nil) {
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.customHeight = height
transitionDelegate.showIndicator = showIndicator
controller.transitioningDelegate = transitionDelegate
controller.modalPresentationStyle = .custom
controller.modalPresentationCapturesStatusBarAppearance = true
+27 -11
View File
@@ -6,7 +6,7 @@ Preview GIF is loading `3mb`. Please, wait.
<img src="https://github.com/IvanVorobei/SPStorkController/blob/master/Resources/Preview.gif" width="500">
You can download example [from AppStore](https://itunes.apple.com/app/id1446635818). Also in the app you can donate me a cup of coffee. If you want to buy source code of the app shown on the GIF above, please go to [xcode-shop.com](https://xcode-shop.com). Price: $200.
You can download example [from AppStore](https://itunes.apple.com/app/id1446635818) or see [video preview](https://xcode-shop.com/assets/preview/debts.mov). If you want to buy source code of the full app (plus app for Apple Watch), please go to [xcode-shop.com](https://xcode-shop.com). Price: $200 only GitHub users!
<img src="https://github.com/IvanVorobei/SPStorkController/blob/master/Resources/Shop.svg"/>
@@ -109,6 +109,10 @@ transitionDelegate.translateForDismiss = 100
```swift
transitionDelegate.tapAroundToDismissEnabled = true
```
- Parameter `showCloseButton` added circle button with dismiss action. Default is `false`:
```swift
transitionDelegate.showCloseButton = false
```
- Parameter `showIndicator` shows or hides top arrow indicator. Default is `true`:
```swift
@@ -120,6 +124,16 @@ transitionDelegate.showIndicator = true
transitionDelegate.indicatorColor = UIColor.white
```
- Parameter `hideIndicatorWhenScroll` shows or hides indicator when scrolling. Default is `false`:
```swift
transitionDelegate.hideIndicatorWhenScroll = true
```
- Parameter `cornerRadius` for customize corner radius of controller's view. Default is `10`:
```swift
transitionDelegate.cornerRadius = 10
```
### Snapshots
The project uses a snapshot of the screen in order to avoid compatibility and customization issues. Before controller presentation, a snapshot of the parent view is made, and size and position are changed for the snapshot. Sometimes you will need to update the screenshot of the parent view, for that use static func:
@@ -135,6 +149,7 @@ You may want to add a navigation bar to your modal controller. Since it became i
```swift
import UIKit
import SPFakeBar
class ModalController: UIViewController {
@@ -158,15 +173,15 @@ You only need to add a navigation bar to the main view, it will automatically la
<img src="https://github.com/IvanVorobei/SPStorkController/blob/master/Resources/Navigation%20Bar.jpg"/>
To use `SPFakeBarView` you need to install [SparrowKit](https://github.com/IvanVorobei/SparrowKit) pod:
To use `SPFakeBarView` you need to install [SPFakeBar](https://github.com/IvanVorobei/SPFakeBar) pod:
```ruby
pod 'SparrowKit'
pod 'SPFakeBar'
```
### Working with UIScrollView
If you use `UIScrollView` (or UITableView & UICollectionView) on your controller, I recommend making it more interactive. When scrolling reaches the top position, the controller will interactively drag down, simulating a closing animation. To do this, set the delegate and in the function `scrollViewDidScroll` call:
If you use `UIScrollView` (or UITableView & UICollectionView) on your controller, I recommend making it more interactive. When scrolling reaches the top position, the controller will interactively drag down, simulating a closing animation. Also available close controller by drag down on `UIScrollView`. To do this, set the delegate and in the function `scrollViewDidScroll` call:
```swift
func scrollViewDidScroll(_ scrollView: UIScrollView) {
@@ -187,6 +202,14 @@ tableView.scrollIndicatorInsets.top = self.navBar.height
Please, also use `SPStorkController.scrollViewDidScroll` function in scroll delegate for more interactiveness with your collection or table view.
### Delegate
You can check events by implement `SPStorkControllerDelegate` and set delegate for `transitionDelegate`:
```swift
transitionDelegate.storkDelegate = self
```
### Modal presentation of different controller
If you want to present modal controller on SPStorkController, please set:
@@ -206,13 +229,6 @@ Project [SPPermission](https://github.com/IvanVorobei/SPPermission) for managing
<img src="https://github.com/IvanVorobei/SPPermission/blob/master/Resources/Preview.gif" width="500">
### SparrowKit
`SPStorkController` was formerly a part of [SparrowKit](https://github.com/IvanVorobei/SparrowKit) library. In the library you can find many useful extensions & classes. To install via CocoaPods use:
```ruby
pod 'SparrowKit'
```
## License
`SPStorkController` is released under the MIT license. Check `LICENSE.md` for details.
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SPStorkController"
s.version = "1.4.7"
s.version = "1.5.7"
s.summary = "Modal controller as mail or Apple music application"
s.homepage = "https://github.com/IvanVorobei/SPStorkController"
s.source = { :git => "https://github.com/IvanVorobei/SPStorkController.git", :tag => s.version }
@@ -0,0 +1,88 @@
import UIKit
class SPStorkCodeDraw : NSObject {
private struct Cache {
static let gradient: CGGradient = CGGradient(colorsSpace: nil, colors: [UIColor.red.cgColor, UIColor.red.cgColor] as CFArray, locations: [0, 1])!
}
@objc dynamic class var gradient: CGGradient { return Cache.gradient }
@objc dynamic class func drawClose(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100), resizing: ResizingBehavior = .aspectFit, color: UIColor = UIColor(red: 0.000, green: 0.000, blue: 0.000, alpha: 1.000)) {
let context = UIGraphicsGetCurrentContext()!
context.saveGState()
let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 100, height: 100), target: targetFrame)
context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
context.scaleBy(x: resizedFrame.width / 100, y: resizedFrame.height / 100)
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 92.02, y: 22.92))
bezierPath.addLine(to: CGPoint(x: 64.42, y: 50.52))
bezierPath.addLine(to: CGPoint(x: 92.02, y: 78.13))
bezierPath.addCurve(to: CGPoint(x: 92.02, y: 92.99), controlPoint1: CGPoint(x: 96.13, y: 82.23), controlPoint2: CGPoint(x: 96.13, y: 88.89))
bezierPath.addCurve(to: CGPoint(x: 84.59, y: 96.07), controlPoint1: CGPoint(x: 89.97, y: 95.05), controlPoint2: CGPoint(x: 87.28, y: 96.07))
bezierPath.addCurve(to: CGPoint(x: 77.16, y: 92.99), controlPoint1: CGPoint(x: 81.9, y: 96.07), controlPoint2: CGPoint(x: 79.22, y: 95.05))
bezierPath.addLine(to: CGPoint(x: 49.55, y: 65.38))
bezierPath.addLine(to: CGPoint(x: 21.95, y: 92.99))
bezierPath.addCurve(to: CGPoint(x: 14.51, y: 96.07), controlPoint1: CGPoint(x: 19.89, y: 95.05), controlPoint2: CGPoint(x: 17.2, y: 96.07))
bezierPath.addCurve(to: CGPoint(x: 7.08, y: 92.99), controlPoint1: CGPoint(x: 11.82, y: 96.07), controlPoint2: CGPoint(x: 9.13, y: 95.05))
bezierPath.addCurve(to: CGPoint(x: 7.08, y: 78.13), controlPoint1: CGPoint(x: 2.97, y: 88.89), controlPoint2: CGPoint(x: 2.97, y: 82.23))
bezierPath.addLine(to: CGPoint(x: 34.69, y: 50.52))
bezierPath.addLine(to: CGPoint(x: 7.08, y: 22.92))
bezierPath.addCurve(to: CGPoint(x: 7.08, y: 8.04), controlPoint1: CGPoint(x: 2.97, y: 18.8), controlPoint2: CGPoint(x: 2.97, y: 12.15))
bezierPath.addCurve(to: CGPoint(x: 21.94, y: 8.04), controlPoint1: CGPoint(x: 11.18, y: 3.94), controlPoint2: CGPoint(x: 17.84, y: 3.94))
bezierPath.addLine(to: CGPoint(x: 49.55, y: 35.65))
bezierPath.addLine(to: CGPoint(x: 77.16, y: 8.04))
bezierPath.addCurve(to: CGPoint(x: 92.02, y: 8.04), controlPoint1: CGPoint(x: 81.26, y: 3.94), controlPoint2: CGPoint(x: 87.92, y: 3.94))
bezierPath.addCurve(to: CGPoint(x: 92.02, y: 22.92), controlPoint1: CGPoint(x: 96.13, y: 12.15), controlPoint2: CGPoint(x: 96.13, y: 18.8))
bezierPath.close()
color.setFill()
bezierPath.fill()
context.restoreGState()
}
@objc(StyleKitNameResizingBehavior)
enum ResizingBehavior: Int {
case aspectFit
case aspectFill
case stretch
case center
func apply(rect: CGRect, target: CGRect) -> CGRect {
if rect == target || target == CGRect.zero {
return rect
}
var scales = CGSize.zero
scales.width = abs(target.width / rect.width)
scales.height = abs(target.height / rect.height)
switch self {
case .aspectFit:
scales.width = min(scales.width, scales.height)
scales.height = scales.width
case .aspectFill:
scales.width = max(scales.width, scales.height)
scales.height = scales.width
case .stretch:
break
case .center:
scales.width = 1
scales.height = 1
}
var result = rect.standardized
result.size.width *= scales.width
result.size.height *= scales.height
result.origin.x = target.minX + (target.width - result.width) / 2
result.origin.y = target.minY + (target.height - result.height) / 2
return result
}
}
private override init() {}
}
@@ -29,12 +29,24 @@ extension UIViewController {
&& presentingViewController != nil
}
public func presentAsStork(_ controller: UIViewController, height: CGFloat? = nil, complection: (() -> Void)? = nil) {
public func presentAsStork(_ controller: UIViewController, height: CGFloat? = nil) {
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.customHeight = height
controller.transitioningDelegate = transitionDelegate
controller.modalPresentationStyle = .custom
controller.modalPresentationCapturesStatusBarAppearance = true
self.present(controller, animated: true, completion: nil)
}
public func presentAsStork(_ controller: UIViewController, height: CGFloat? = nil, showIndicator: Bool = false, hideIndicatorWhenScroll: Bool, showCloseButton: Bool = false, complection: (() -> Void)? = nil) {
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.customHeight = height
transitionDelegate.showCloseButton = showCloseButton
transitionDelegate.showIndicator = showIndicator
transitionDelegate.hideIndicatorWhenScroll = hideIndicatorWhenScroll
controller.transitioningDelegate = transitionDelegate
controller.modalPresentationStyle = .custom
controller.modalPresentationCapturesStatusBarAppearance = true
self.present(controller, animated: true, completion: complection)
}
}
@@ -0,0 +1,29 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import UIKit
@objc public protocol SPStorkControllerDelegate: class {
@objc optional func didDismissStorkBySwipe()
@objc optional func didDismissStorkByTap()
}
+23 -7
View File
@@ -25,27 +25,43 @@ public struct SPStorkController {
static public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let controller = self.controller(for: scrollView) {
if let presentationController = controller.presentationController as? SPStorkPresentationController,
presentationController.swipeToDismissEnabled {
if let presentationController = controller.presentationController as? SPStorkPresentationController {
let translation = -(scrollView.contentOffset.y + scrollView.contentInset.top)
if translation >= 0 {
if controller.isBeingPresented { return }
scrollView.subviews.forEach {
$0.transform = CGAffineTransform(translationX: 0, y: -translation)
}
if let pan = presentationController.pan,
pan.state == .possible, pan.translation(in: controller.view).y <= 0 {
presentationController.scrollViewDidScroll(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.storkDelegate?.didDismissStorkBySwipe?()
})
return
}
}
if presentationController.pan?.state != UIGestureRecognizer.State.changed {
presentationController.scrollViewDidScroll(translation * 2)
}
} else {
presentationController.setIndicator(style: .arrow)
presentationController.scrollViewDidScroll(0)
}
if translation < -15 {
presentationController.setIndicator(visible: false)
} else {
presentationController.setIndicator(visible: true)
}
}
}
}
static var topScrollIndicatorInset: CGFloat {
return 6
}
static public func updatePresentingController(parent controller: UIViewController) {
if let presentationController = controller.presentedViewController?.presentationController as? SPStorkPresentationController {
presentationController.updatePresentingController()
@@ -29,8 +29,10 @@ final class SPStorkDismissingAnimationController: NSObject, UIViewControllerAnim
return
}
let finalFrameForPresentedView = transitionContext.finalFrame(for: presentedViewController)
let containerView = transitionContext.containerView
let offscreenFrame = CGRect(x: 0, y: containerView.bounds.height, width: containerView.bounds.width, height: containerView.bounds.height)
let offscreenFrame = CGRect(x: 0, y: containerView.bounds.height, width: finalFrameForPresentedView.width, height: finalFrameForPresentedView.height)
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
@@ -25,16 +25,20 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
var swipeToDismissEnabled: Bool = true
var tapAroundToDismissEnabled: Bool = true
var showCloseButton: Bool = false
var showIndicator: Bool = true
var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
var hideIndicatorWhenScroll: Bool = false
var customHeight: CGFloat? = nil
var translateForDismiss: CGFloat = 240
var translateForDismiss: CGFloat = 200
var transitioningDelegate: SPStorkTransitioningDelegate?
weak var storkDelegate: SPStorkControllerDelegate?
var pan: UIPanGestureRecognizer?
var tap: UITapGestureRecognizer?
private var closeButton = SPStorkCloseButton()
private var indicatorView = SPStorkIndicatorView()
private var gradeView: UIView = UIView()
private let snapshotViewContainer = UIView()
@@ -44,6 +48,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
private var snapshotViewTopConstraint: NSLayoutConstraint?
private var snapshotViewWidthConstraint: NSLayoutConstraint?
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
private var workGester: Bool = false
private var startDismissing: Bool = false
@@ -52,13 +57,8 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
return (statusBarHeight < 25) ? 30 : statusBarHeight
}
private var alpha: CGFloat {
return 0.51
}
private var cornerRadius: CGFloat {
return 10
}
private let alpha: CGFloat = 0.51
var cornerRadius: CGFloat = 10
private var scaleForPresentingView: CGFloat {
guard let containerView = containerView else { return 0 }
@@ -68,14 +68,20 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
override var frameOfPresentedViewInContainerView: CGRect {
guard let containerView = containerView else { return .zero }
var customHeight = self.customHeight ?? containerView.bounds.height
if customHeight > containerView.bounds.height {
customHeight = containerView.bounds.height
print("SPStorkController - Custom height change to default value. Your height more maximum value")
}
let additionTranslate = containerView.bounds.height - customHeight
let yOffset: CGFloat = self.topSpace + 13 + additionTranslate
let yOffset: CGFloat = {
if customHeight < containerView.bounds.height {
return additionTranslate
} else {
return self.topSpace + 13 + additionTranslate
}
}()
return CGRect(x: 0, y: yOffset, width: containerView.bounds.width, height: containerView.bounds.height - yOffset)
}
@@ -95,6 +101,12 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.indicatorView.style = .arrow
self.gradeView.alpha = 0
if self.showCloseButton {
self.closeButton.addTarget(self, action: #selector(self.dismissAction), for: .touchUpInside)
presentedView.addSubview(self.closeButton)
}
self.updateLayoutCloseButton()
let initialFrame: CGRect = presentingViewController.isPresentedAsStork ? presentingViewController.view.frame : containerView.bounds
containerView.insertSubview(self.snapshotViewContainer, belowSubview: presentedViewController.view)
@@ -190,7 +202,9 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
@objc func dismissAction() {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: nil)
self.presentedViewController.dismiss(animated: true, completion: {
self.storkDelegate?.didDismissStorkByTap?()
})
}
override func dismissalTransitionWillBegin() {
@@ -262,6 +276,8 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.backgroundView.removeFromSuperview()
self.snapshotView?.removeFromSuperview()
self.snapshotViewContainer.removeFromSuperview()
self.indicatorView.removeFromSuperview()
self.closeButton.removeFromSuperview()
let offscreenFrame = CGRect(x: 0, y: containerView.bounds.height, width: containerView.bounds.width, height: containerView.bounds.height)
presentedViewController.view.frame = offscreenFrame
@@ -294,7 +310,9 @@ extension SPStorkPresentationController {
self.workGester = false
let translation = gestureRecognizer.translation(in: presentedView).y
if translation >= self.translateForDismiss {
presentedViewController.dismiss(animated: true, completion: nil)
self.presentedViewController.dismiss(animated: true, completion: {
self.storkDelegate?.didDismissStorkBySwipe?()
})
} else {
self.indicatorView.style = .arrow
UIView.animate(
@@ -325,6 +343,21 @@ extension SPStorkPresentationController {
self.updateSnapshot()
}
func setIndicator(style: SPStorkIndicatorView.Style) {
self.indicatorView.style = style
}
func setIndicator(visible: Bool) {
guard self.hideIndicatorWhenScroll else { return }
let newAlpha: CGFloat = visible ? 1 : 0
if self.indicatorView.alpha == newAlpha {
return
}
UIView.animate(withDuration: 0.22, animations: {
self.indicatorView.alpha = newAlpha
})
}
private func updatePresentedViewForTranslation(inVerticalDirection translation: CGFloat) {
if self.startDismissing { return }
@@ -344,22 +377,18 @@ extension SPStorkPresentationController {
self.presentedView?.transform = CGAffineTransform(translationX: 0, y: translationForModal)
let factor = 1 + (translationForModal / 6000)
self.snapshotView?.transform = CGAffineTransform.init(scaleX: factor, y: factor)
self.gradeView.alpha = self.alpha - ((factor - 1) * 15)
let scaleFactor = 1 + (translationForModal / 5000)
self.snapshotView?.transform = CGAffineTransform.init(scaleX: scaleFactor, y: scaleFactor)
let gradeFactor = 1 + (translationForModal / 7000)
self.gradeView.alpha = self.alpha - ((gradeFactor - 1) * 15)
} else {
self.presentedView?.transform = CGAffineTransform.identity
}
}
}
extension SPStorkPresentationController {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if swipeToDismissEnabled, let scrollView = otherGestureRecognizer.view as? UIScrollView{
return scrollView.contentOffset.y <= 0
}
return false
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
guard let containerView = containerView else { return }
@@ -376,6 +405,7 @@ extension SPStorkPresentationController {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { contex in
self.updateLayoutIndicator()
self.updateLayoutCloseButton()
}, completion: { [weak self] _ in
self?.updateSnapshotAspectRatio()
self?.updateSnapshot()
@@ -390,6 +420,12 @@ extension SPStorkPresentationController {
self.indicatorView.center.x = presentedView.frame.width / 2
}
private func updateLayoutCloseButton() {
guard let presentedView = self.presentedView else { return }
self.closeButton.sizeToFit()
self.closeButton.layout(bottomX: presentedView.frame.width - 19, y: 19)
}
private func updateSnapshot() {
guard let currentSnapshotView = presentingViewController.view.snapshotView(afterScreenUpdates: true) else { return }
self.snapshotView?.removeFromSuperview()
@@ -25,20 +25,28 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
public var swipeToDismissEnabled: Bool = true
public var tapAroundToDismissEnabled: Bool = true
public var showCloseButton: Bool = false
public var showIndicator: Bool = true
public var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
public var hideIndicatorWhenScroll: Bool = false
public var customHeight: CGFloat? = nil
public var translateForDismiss: CGFloat = 240
public var translateForDismiss: CGFloat = 200
public var cornerRadius: CGFloat = 10
public weak var storkDelegate: SPStorkControllerDelegate? = nil
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
let controller = SPStorkPresentationController(presentedViewController: presented, presenting: presenting)
controller.swipeToDismissEnabled = self.swipeToDismissEnabled
controller.tapAroundToDismissEnabled = self.tapAroundToDismissEnabled
controller.showCloseButton = self.showCloseButton
controller.showIndicator = self.showIndicator
controller.indicatorColor = self.indicatorColor
controller.hideIndicatorWhenScroll = self.hideIndicatorWhenScroll
controller.customHeight = self.customHeight
controller.translateForDismiss = self.translateForDismiss
controller.cornerRadius = self.cornerRadius
controller.transitioningDelegate = self
controller.storkDelegate = self.storkDelegate
return controller
}
@@ -0,0 +1,78 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import UIKit
open class SPStorkCloseButton: UIButton {
let iconView = SPStorkCloseView()
var widthIconFactor: CGFloat = 1
var heightIconFactor: CGFloat = 1
var color = UIColor.blue {
didSet {
self.iconView.color = self.color
}
}
override open var isHighlighted: Bool {
didSet {
self.iconView.color = self.color.withAlphaComponent(self.isHighlighted ? 0.7 : 1)
}
}
init() {
super.init(frame: .zero)
self.commonInit()
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func commonInit() {
self.iconView.isUserInteractionEnabled = false
self.addSubview(self.iconView)
self.backgroundColor = UIColor.init(red: 239 / 255.0, green: 239 / 255.0, blue: 244 / 255.0, alpha: 1)
self.color = UIColor.init(red: 142 / 255.0, green: 142 / 255.0, blue: 147 / 255.0, alpha: 1)
self.widthIconFactor = 0.36
self.heightIconFactor = 0.36
}
func layout(bottomX: CGFloat, y: CGFloat) {
self.sizeToFit()
self.frame.origin.x = bottomX - self.frame.width
self.frame.origin.y = y
}
override open func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.frame.width / 2
self.iconView.frame = CGRect.init(x: 0, y: 0, width: self.frame.width * self.widthIconFactor, height: self.frame.height * self.heightIconFactor)
self.iconView.center = CGPoint.init(x: self.frame.width / 2, y: self.frame.height / 2)
}
override open func sizeToFit() {
super.sizeToFit()
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: 30, height: 30)
}
}
@@ -0,0 +1,50 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import UIKit
open class SPStorkCloseView: UIView {
var color = UIColor.blue {
didSet {
self.setNeedsDisplay()
}
}
init() {
super.init(frame: CGRect.zero)
self.commonInit()
}
private func commonInit() {
self.backgroundColor = UIColor.clear
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override open func draw(_ rect: CGRect) {
super.draw(rect)
SPStorkCodeDraw.drawClose(frame: rect, resizing: .aspectFit, color: self.color)
}
}