Compare commits

...

33 Commits

Author SHA1 Message Date
Ivan Vorobei 84256152dc Update to 1.6
Update duration animation for show / hide indicator view when scrolling.
2019-03-26 14:19:27 +03:00
Ivan Vorobei ac366c84fd Update to 1.5.8 2019-03-25 23:30:30 +03:00
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
Ivan Vorobei 39c30a030d Update SPStorkController.podspec 2019-02-19 12:31:58 +03:00
Ivan Vorobei 9e4f6e086f Update to 1.4.6
Added dismiss trigger when scrollView is scrolling down. Also added `swipeToDismissEnabled` checking to allow scrollView bounce when `swipeToDismissEnabled` is disabled.
2019-02-19 12:17:46 +03:00
Ivan Vorobei 5bc31cdc57 Merge pull request #37 from ilia3546/master
Added dismiss trigger when scrollView is scrolling down. Also added `swipeToDismissEnabled` checking to allow scrollView bounce when `swipeToDismissEnabled` is disabled.
2019-02-19 12:05:30 +03:00
Ilya Kharlamov 7d53ed31e6 Fix 2019-02-18 14:26:57 +03:00
Ilya Kharlamov 80806de694 Fix 2019-02-18 14:20:58 +03:00
Ilya Kharlamov 8d8458cc34 Revert "Custom width;"
This reverts commit dd2b29f27a.
2019-02-18 13:58:19 +03:00
Ilya Kharlamov 6e09df910e Custom width;
Ability to disable snapshot scaling;
2019-02-18 13:50:00 +03:00
Ilya Kharlamov 253f60cfa9 ScrollView with disabled swipeToDismissEnabled fixed;
Added trigger for dismissing when view is scrolling down;
2019-02-18 13:10:29 +03:00
Ivan Vorobei 81ed7b01cd Fix some bugs
Fix bug when present 2 or more controllers with custom heights. Also fix bug with grade for `presentingController` view.
2019-02-14 00:23:35 +03:00
Ivan Vorobei d0f120d49c Remove old code 2019-02-09 15:04:10 +03:00
Ivan Vorobei bc3555e715 Update README.md 2019-02-09 09:50:20 +03:00
Ivan Vorobei 432a1206cf Update README.md 2019-02-09 09:48:04 +03:00
Ivan Vorobei 488b19fc46 Update README.md 2019-02-09 09:29:22 +03:00
Ivan Vorobei edc2b6ea41 Fix example of table view 2019-02-09 09:27:13 +03:00
Ivan Vorobei 79d64599d0 Update SPStorkController.podspec 2019-02-08 19:02:59 +03:00
Ivan Vorobei 854ab2aef2 Fix bug
for update translation for scroll when presentng controller
2019-02-08 19:00:17 +03:00
Ivan Vorobei 04c4929e7d Update Readme.md 2019-02-08 18:20:47 +03:00
Ivan Vorobei 6e4e9713c3 Update example 2019-02-07 23:06:41 +03:00
82 changed files with 1457 additions and 954 deletions
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -21,7 +21,7 @@ class Controller: UIViewController {
self.presentTableControllerButton.addTarget(self, action: #selector(self.presentModalTableViewController), for: .touchUpInside)
self.presentTableControllerButton.sizeToFit()
self.presentTableControllerButton.center.x = self.view.frame.width / 2
self.presentTableControllerButton.frame.origin.y = self.presentControllerButton.frame.bottomYPosition + 10
self.presentTableControllerButton.frame.origin.y = self.presentControllerButton.frame.bottomY + 10
self.view.addSubview(self.presentTableControllerButton)
}
+14 -1
View File
@@ -28,19 +28,32 @@ public struct SPStorkController {
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)
}
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)
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()
@@ -23,11 +23,13 @@ import UIKit
class SPStorkPresentationController: UIPresentationController, UIGestureRecognizerDelegate {
var isSwipeToDismissEnabled: Bool = true
var isTapAroundToDismissEnabled: Bool = true
var swipeToDismissEnabled: Bool = true
var tapAroundToDismissEnabled: Bool = true
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 = 200
var transitioningDelegate: SPStorkTransitioningDelegate?
var pan: UIPanGestureRecognizer?
@@ -42,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
@@ -50,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 }
@@ -84,7 +82,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
if self.showIndicator {
self.indicatorView.color = self.indicatorColor
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.handleTap))
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
tap.cancelsTouchesInView = false
self.indicatorView.addGestureRecognizer(tap)
presentedView.addSubview(self.indicatorView)
@@ -133,8 +131,9 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
containerView.insertSubview(snapshotView, aboveSubview: self.backgroundView)
snapshotView.frame = initialFrame
snapshotView.transform = transformForSnapshotView
snapshotView.alpha = self.alpha
snapshotView.alpha = 1 - self.alpha
snapshotView.layer.cornerRadius = self.cornerRadius
snapshotView.contentMode = .top
snapshotView.layer.masksToBounds = true
rootSnapshotView = snapshotView
@@ -169,13 +168,13 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
self.snapshotViewContainer.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
self.updateSnapshotAspectRatio()
if self.isTapAroundToDismissEnabled {
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.handleTap))
if self.tapAroundToDismissEnabled {
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
self.tap?.cancelsTouchesInView = false
self.snapshotViewContainer.addGestureRecognizer(self.tap!)
}
if self.isSwipeToDismissEnabled {
if self.swipeToDismissEnabled {
self.pan = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan))
self.pan!.delegate = self
self.pan!.maximumNumberOfTouches = 1
@@ -184,7 +183,9 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
}
}
@objc func handleTap() {
@objc func dismissAction() {
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
self.presentedViewController.dismiss(animated: true, completion: nil)
}
@@ -223,6 +224,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
containerView.insertSubview(snapshotView, aboveSubview: backgroundView)
snapshotView.frame = initialFrame
snapshotView.transform = initialTransform
snapshotView.contentMode = .top
rootSnapshotView = snapshotView
snapshotView.layer.cornerRadius = self.cornerRadius
snapshotView.layer.masksToBounds = true
@@ -230,7 +232,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
let snapshotRoundedView = UIView()
snapshotRoundedView.layer.cornerRadius = self.cornerRadius
snapshotRoundedView.layer.masksToBounds = true
snapshotRoundedView.backgroundColor = UIColor.black.withAlphaComponent(1 - self.alpha)
snapshotRoundedView.backgroundColor = UIColor.black.withAlphaComponent(self.alpha)
containerView.insertSubview(snapshotRoundedView, aboveSubview: snapshotView)
snapshotRoundedView.frame = initialFrame
snapshotRoundedView.transform = initialTransform
@@ -266,7 +268,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
extension SPStorkPresentationController {
@objc func handlePan(gestureRecognizer: UIPanGestureRecognizer) {
guard gestureRecognizer.isEqual(pan), self.isSwipeToDismissEnabled else { return }
guard gestureRecognizer.isEqual(self.pan), self.swipeToDismissEnabled else { return }
switch gestureRecognizer.state {
case .began:
@@ -278,7 +280,7 @@ extension SPStorkPresentationController {
gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: containerView)
case .changed:
self.workGester = true
if self.isSwipeToDismissEnabled {
if self.swipeToDismissEnabled {
let translation = gestureRecognizer.translation(in: presentedView)
self.updatePresentedViewForTranslation(inVerticalDirection: translation.y)
} else {
@@ -287,8 +289,8 @@ extension SPStorkPresentationController {
case .ended:
self.workGester = false
let translation = gestureRecognizer.translation(in: presentedView).y
if translation >= 240 {
presentedViewController.dismiss(animated: true, completion: nil)
if translation >= self.translateForDismiss {
self.presentedViewController.dismiss(animated: true, completion: nil)
} else {
self.indicatorView.style = .arrow
UIView.animate(
@@ -319,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 }
@@ -338,9 +344,12 @@ 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
}
}
}
@@ -25,15 +25,14 @@ final class SPStorkPresentingAnimationController: NSObject, UIViewControllerAnim
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let presentedViewController = transitionContext.viewController(forKey: .to) else {
return
}
guard let presentedViewController = transitionContext.viewController(forKey: .to) else { return }
let containerView = transitionContext.containerView
containerView.addSubview(presentedViewController.view)
presentedViewController.view.frame = CGRect(x: 0, y: containerView.bounds.height, width: containerView.bounds.width, height: containerView.bounds.height)
let finalFrameForPresentedView = transitionContext.finalFrame(for: presentedViewController)
presentedViewController.view.frame = finalFrameForPresentedView
presentedViewController.view.frame.origin.y = containerView.bounds.height
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
@@ -23,19 +23,23 @@ import UIKit
public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
public var isSwipeToDismissEnabled: Bool = true
public var isTapAroundToDismissEnabled: Bool = true
public var swipeToDismissEnabled: Bool = true
public var tapAroundToDismissEnabled: Bool = true
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 = 200
public var cornerRadius: CGFloat = 10
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
let controller = SPStorkPresentationController(presentedViewController: presented, presenting: presenting)
controller.isSwipeToDismissEnabled = self.isSwipeToDismissEnabled
controller.isTapAroundToDismissEnabled = self.isTapAroundToDismissEnabled
controller.swipeToDismissEnabled = self.swipeToDismissEnabled
controller.tapAroundToDismissEnabled = self.tapAroundToDismissEnabled
controller.showIndicator = self.showIndicator
controller.indicatorColor = self.indicatorColor
controller.customHeight = self.customHeight
controller.translateForDismiss = self.translateForDismiss
controller.cornerRadius = self.cornerRadius
controller.transitioningDelegate = self
return controller
}
@@ -29,10 +29,13 @@ extension UIViewController {
&& presentingViewController != nil
}
public func presentAsStork(_ controller: UIViewController, 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
self.present(controller, animated: true, completion: complection)
}
}
@@ -47,7 +47,7 @@ public class SPAnimation {
withComplection completion: (() -> Void)! = {}) {
var optionsWithRepeatition = options
optionsWithRepeatition.insert([.autoreverse, .repeat])
optionsWithRepeatition.insert([.autoreverse, .repeat, .allowUserInteraction])
self.animate(
duration,
@@ -36,6 +36,14 @@ struct SPApp {
return UIApplication.shared.keyWindow?.rootViewController
}
public static var safeArea: UIEdgeInsets {
if #available(iOS 11.0, *) {
return UIApplication.shared.keyWindow?.safeArea ?? UIEdgeInsets.zero
} else {
return UIEdgeInsets.zero
}
}
public static func set(rootController: UIViewController, animatable: Bool = true) {
rootController.view.frame = UIScreen.main.bounds
@@ -28,8 +28,8 @@ struct SPAppStore {
return "https://itunes.apple.com/by/app/id" + appID
}
public static func open(appID: String) {
if let url = URL(string: "itms-apps://itunes.apple.com/app/id\(appID)"),
public static func open(app id: String) {
if let url = URL(string: "itms-apps://itunes.apple.com/app/id\(id)"),
UIApplication.shared.canOpenURL(url) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
@@ -29,7 +29,7 @@ public struct SPAudio {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category(rawValue: convertFromAVAudioSessionCategory(AVAudioSession.Category.ambient)), mode: AVAudioSession.Mode.default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("SPAudio - notStopBackgroundMusic, error")
}
}
@@ -23,17 +23,29 @@ import UIKit
extension CGRect {
public var bottomXPosition: CGFloat {
public var bottomX: CGFloat {
get { return self.origin.x + self.width }
set { self.origin.x = newValue - self.width }
}
public var bottomYPosition: CGFloat {
public var bottomY: CGFloat {
get { return self.origin.y + self.height }
set { self.origin.y = newValue - self.height }
}
public var minSideSize: CGFloat {
public var minSide: CGFloat {
return min(self.width, self.height)
}
public mutating func set(width: CGFloat) {
self = CGRect.init(x: self.origin.x, y: self.origin.y, width: width, height: self.height)
}
public mutating func set(height: CGFloat) {
self = CGRect.init(x: self.origin.x, y: self.origin.y, width: self.width, height: height)
}
public mutating func set(width: CGFloat, height: CGFloat) {
self = CGRect.init(x: self.origin.x, y: self.origin.y, width: width, height: height)
}
}
@@ -70,6 +70,14 @@ extension String {
return false
}
public var isEmpty: Bool {
return (self.removeAllSpaces() == "")
}
public var words: [String] {
return components(separatedBy: .punctuationCharacters).joined().components(separatedBy: .whitespaces)
}
public mutating func replace(_ replacingString: String, with newString: String) {
self = self.replacingOccurrences(of: replacingString, with: newString)
}
@@ -39,13 +39,12 @@ extension UIAlertController {
preferredStyle: .alert
)
if cancelButtonTitle != nil {
ac.addAction(UIAlertAction.init(
title: cancelButtonTitle!,
style: UIAlertAction.Style.cancel,
handler: nil)
)
}
guard cancelButtonTitle != nil else { return }
ac.addAction(UIAlertAction.init(
title: cancelButtonTitle!,
style: UIAlertAction.Style.cancel,
handler: nil)
)
ac.addAction(UIAlertAction.init(
title: buttonTitle,
@@ -64,10 +63,8 @@ extension UIAlertController {
preferredStyle: .actionSheet
)
var style = UIAlertAction.Style.default
if isDestructive {
style = .destructive
}
let style = isDestructive ? .destructive : UIAlertAction.Style.default
ac.addAction(UIAlertAction.init(
title: buttonTitle,
style: style,
@@ -76,11 +73,10 @@ extension UIAlertController {
}))
ac.addAction(UIAlertAction.init(
title: cancelButtonTitle,
style: UIAlertAction.Style.default,
style: UIAlertAction.Style.cancel,
handler: { (action) in
complection(false)
}))
viewController.present(ac, animated: true, completion: nil)
}
}
@@ -60,8 +60,11 @@ extension UIButton {
extension UIButton {
public func setTitle(_ title: String) {
public func setTitle(_ title: String, color: UIColor? = nil) {
self.setTitle(title, for: .normal)
if let color = color {
self.setTitleColor(color)
}
}
public func setTitleColor(_ color: UIColor) {
@@ -69,6 +72,11 @@ extension UIButton {
self.setTitleColor(color.withAlphaComponent(0.7), for: .highlighted)
}
public func setImage(_ image: UIImage) {
self.setImage(image, for: .normal)
self.imageView?.contentMode = .scaleAspectFit
}
public func removeAllTargets() {
self.removeTarget(nil, action: nil, for: .allEvents)
}
@@ -111,7 +119,7 @@ extension UIButton {
}
public func hideContent(completion: (() -> Void)! = {}) {
SPAnimation.animate(0.2, animations: {
SPAnimation.animate(0.25, animations: {
self.titleLabel?.alpha = 0
}, withComplection: {
completion()
@@ -119,7 +127,7 @@ extension UIButton {
}
public func showContent(completion: (() -> Void)! = {}) {
SPAnimation.animate(0.2, animations: {
SPAnimation.animate(0.25, animations: {
self.titleLabel?.alpha = 1
}, withComplection: {
completion()
@@ -23,40 +23,39 @@ import UIKit
public extension UIFont {
public static func system(type: BoldType, size: CGFloat) -> UIFont {
return UIFont.systemFont(ofSize: size, weight: self.getBoldTypeBy(boldType: type))
public static func system(weight: FontWeight, size: CGFloat) -> UIFont {
return UIFont.systemFont(ofSize: size, weight: self.weight(for: weight))
}
@available(iOS 8.2, *)
private static func getBoldTypeBy(boldType: BoldType) -> UIFont.Weight {
switch boldType {
case .UltraLight:
private static func weight(for weight: FontWeight) -> UIFont.Weight {
switch weight {
case .ultraLight:
return UIFont.Weight.ultraLight
case .Light:
case .light:
return UIFont.Weight.light
case .Medium:
case .medium:
return UIFont.Weight.medium
case .Regular:
case .regular:
return UIFont.Weight.regular
case .Bold:
case .bold:
return UIFont.Weight.bold
case .DemiBold:
case .demiBold:
return UIFont.Weight.semibold
case .Heavy:
case .heavy:
return UIFont.Weight.heavy
default:
return UIFont.Weight.regular
}
}
public enum BoldType {
case Regular
case Medium
case Light
case UltraLight
case Heavy
case Bold
case DemiBold
case None
public enum FontWeight {
case regular
case medium
case light
case ultraLight
case heavy
case bold
case demiBold
case none
}
}
@@ -32,4 +32,12 @@ public extension UIImage {
UIGraphicsEndImageContext()
return newImage!
}
var alwaysOriginal: UIImage {
return self.withRenderingMode(.alwaysOriginal)
}
var alwaysTemplate: UIImage {
return self.withRenderingMode(.alwaysTemplate)
}
}
@@ -42,7 +42,7 @@ public extension UILabel {
self.setShadowOffsetForLetters(blurRadius: 0, widthOffset: 0, heightOffset: 0, opacity: 0)
}
public func setCenteringAlignment() {
public func setCenterAlignment() {
self.textAlignment = .center
self.baselineAdjustment = .alignCenters
}
@@ -54,7 +54,7 @@ public extension UILabel {
}
}
public func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
public func setLineSpacing(_ lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
@@ -71,7 +71,6 @@ public extension UILabel {
attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
@@ -42,24 +42,11 @@ public extension UIView {
}
}
public func set(width: CGFloat, height: CGFloat) {
self.setHeight(height)
self.setWidth(width)
public func setBounds(_ view: UIView, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
self.setBounds(view.bounds, withWidthFactor: widthFactor, maxWidth: maxWidth, withHeightFactor: heightFactor, maxHeight: maxHeight, withCentering: withCentering)
}
public func setHeight(_ height: CGFloat) {
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: self.frame.width, height: height)
}
public func setWidth(_ width: CGFloat) {
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: width, height: self.frame.height)
}
public func setEqualsFrameFromBounds(_ view: UIView, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
self.setEqualsFrameFromBounds(view.bounds, withWidthFactor: widthFactor, maxWidth: maxWidth, withHeightFactor: heightFactor, maxHeight: maxHeight, withCentering: withCentering)
}
public func setEqualsFrameFromBounds(_ bounds: CGRect, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
public func setBounds(_ bounds: CGRect, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
var width = bounds.width * widthFactor
if maxWidth != nil { width.setIfMore(when: maxWidth!) }
@@ -75,7 +62,7 @@ public extension UIView {
}
}
public func setEqualsBoundsFromSuperview(customWidth: CGFloat? = nil, customHeight: CGFloat? = nil) {
public func setSuperviewBounds(customWidth: CGFloat? = nil, customHeight: CGFloat? = nil) {
if self.superview == nil { return }
self.frame = CGRect.init(origin: CGPoint.zero, size: self.superview!.frame.size)
if customWidth != nil {
@@ -108,15 +95,15 @@ public extension UIView {
)
}
public func setYCenteringFromSuperview() {
public func setYCenter() {
self.center.y = (self.superview?.frame.height ?? 0) / 2
}
public func setXCenteringFromSuperview() {
public func setXCenter() {
self.center.x = (self.superview?.frame.width ?? 0) / 2
}
public func setToCenterInSuperview() {
public func setToCenter() {
self.center = CGPoint.init(x: ((self.superview?.frame.width) ?? 0) / 2, y: ((self.superview?.frame.height) ?? 0) / 2)
}
}
@@ -124,7 +111,7 @@ public extension UIView {
public extension UIView {
public func setParalax(amountFactor: CGFloat) {
let amount = self.frame.minSideSize * amountFactor
let amount = self.frame.minSide * amountFactor
self.setParalax(amount: amount)
}
@@ -174,14 +161,14 @@ extension UIView {
let xTranslation = (self.frame.width - shadowWidth) / 2 + (self.frame.width * xTranslationFactor)
let yTranslation = (self.frame.height - shadowHeight) / 2 + (self.frame.height * yTranslationFactor)
let cornerRadius = self.frame.minSideSize * cornerRadiusFactor
let cornerRadius = self.frame.minSide * cornerRadiusFactor
let shadowPath = UIBezierPath.init(
roundedRect: CGRect.init(x: xTranslation, y: yTranslation, width: shadowWidth, height: shadowHeight),
cornerRadius: cornerRadius
)
let blurRadius = self.frame.minSideSize * blurRadiusFactor
let blurRadius = self.frame.minSide * blurRadiusFactor
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize.zero
@@ -277,6 +264,6 @@ extension UIView {
}
public func round() {
self.layer.cornerRadius = self.frame.minSideSize / 2
self.layer.cornerRadius = self.frame.minSide / 2
}
}
@@ -66,7 +66,7 @@ extension SPShadow {
yTranslation = view.frame.height + maxBottomSpace - shadowHeight
}
var blurRadius = view.frame.minSideSize * blurRadiusFactor
var blurRadius = view.frame.minSide * blurRadiusFactor
blurRadius.setIfMore(when: 10)
blurRadius.setIfFewer(when: 7)
@@ -26,7 +26,7 @@ public enum SPStatusBar {
case light
}
public enum SPSystemIconType {
public enum SPSystemIcon {
case share
case close
case favorite
@@ -32,28 +32,28 @@ public class SPAppStoreActionButton: SPDownloadingButton {
switch self.style {
case .base:
self.backgroundColor = self.secondColor
self.titleLabel?.font = UIFont.system(type: .Bold, size: 14)
self.titleLabel?.font = UIFont.system(weight: .bold, size: 14)
self.contentEdgeInsets = UIEdgeInsets.init(top: 6, left: 15, bottom: 6, right: 15)
break
case .main:
self.backgroundColor = self.baseColor
self.layer.borderWidth = 0
self.setTitleColor(UIColor.white)
self.titleLabel?.font = UIFont.system(type: .Bold, size: 14)
self.titleLabel?.font = UIFont.system(weight: .bold, size: 14)
self.contentEdgeInsets = UIEdgeInsets.init(top: 6, left: 15, bottom: 6, right: 15)
break
case .buyInStore:
self.backgroundColor = self.baseColor
self.layer.borderWidth = 0
self.setTitleColor(UIColor.white)
self.titleLabel?.font = UIFont.system(type: .Bold, size: 14)
self.titleLabel?.font = UIFont.system(weight: .bold, size: 14)
self.contentEdgeInsets = UIEdgeInsets.init(top: 8, left: 15, bottom: 8, right: 15)
break
case .line:
self.backgroundColor = UIColor.clear
self.layer.borderWidth = 1
self.layer.borderColor = self.baseColor.cgColor
self.titleLabel?.font = UIFont.system(type: .Medium, size: 14)
self.titleLabel?.font = UIFont.system(weight: .medium, size: 14)
self.contentEdgeInsets = UIEdgeInsets.init(top: 6, left: 15, bottom: 6, right: 15)
break
}
@@ -44,7 +44,7 @@ public class SPAppleMusicButton: SPButton {
override func commonInit() {
super.commonInit()
self.layer.cornerRadius = 8
self.titleLabel?.font = UIFont.system(type: .DemiBold, size: 15)
self.titleLabel?.font = UIFont.system(weight: .demiBold, size: 15)
self.contentEdgeInsets = UIEdgeInsets.init(top: 12, left: 27, bottom: 12, right: 27)
self.type = .unselect
}
@@ -64,7 +64,7 @@ public class SPAppleMusicSectionButtonsView: SPView {
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.set(width: width, height: sectionHeight)
self.frame.set(width: width, height: sectionHeight)
self.layoutSubviews()
}
@@ -72,22 +72,22 @@ public class SPAppleMusicSectionButtonsView: SPView {
super.layoutSubviews()
self.topSeparatorView.frame.origin = .zero
self.topSeparatorView.setWidth(self.frame.width)
self.topSeparatorView.frame.set(width: self.frame.width)
self.bottomSeparatorView.frame.origin.x = 0
self.bottomSeparatorView.frame.bottomYPosition = self.frame.height
self.bottomSeparatorView.setWidth(self.frame.width)
self.bottomSeparatorView.frame.bottomY = self.frame.height
self.bottomSeparatorView.frame.set(width: self.frame.width)
let buttonWidth = (self.frame.width - self.buttonsSpace) / 2
self.leftButton.sizeToFit()
self.leftButton.setWidth(buttonWidth)
self.leftButton.frame.set(width: buttonWidth)
self.leftButton.frame.origin.x = 0
self.leftButton.center.y = self.frame.height / 2
self.rightButton.sizeToFit()
self.rightButton.setWidth(buttonWidth)
self.rightButton.frame.bottomXPosition = self.frame.width
self.rightButton.frame.set(width: buttonWidth)
self.rightButton.frame.bottomX = self.frame.width
self.rightButton.center.y = self.frame.height / 2
}
}
@@ -23,7 +23,28 @@ import UIKit
public class SPButton: UIButton {
var gradientView: SPGradientView? {
override public func imageRect(forContentRect contentRect: CGRect) -> CGRect {
if self.title(for: .normal) != nil {
let inset: CGFloat = 6
let sideSize = self.frame.height - inset * 2
let titleFrame = self.titleRect(forContentRect: contentRect)
return CGRect.init(x: titleFrame.origin.x - sideSize - 6, y: 0, width: sideSize, height: self.frame.height)
} else {
return super.imageRect(forContentRect: contentRect)
}
}
override public var isHighlighted: Bool{
didSet {
if self.isHighlighted {
self.imageView?.alpha = 0.7
} else {
self.imageView?.alpha = 1
}
}
}
public var gradientView: SPGradientView? {
didSet {
self.gradientView?.isUserInteractionEnabled = false
if self.gradientView?.superview == nil {
@@ -34,7 +55,7 @@ public class SPButton: UIButton {
}
}
var round: Bool = false {
public var rounded: Bool = false {
didSet {
self.layoutSubviews()
}
@@ -50,13 +71,26 @@ public class SPButton: UIButton {
self.commonInit()
}
internal func commonInit() {}
internal func commonInit() {
self.adjustsImageWhenHighlighted = false
}
override public func layoutSubviews() {
super.layoutSubviews()
self.gradientView?.setEqualsBoundsFromSuperview()
if self.round {
self.gradientView?.setSuperviewBounds()
if self.rounded {
self.round()
}
}
public func set(enable: Bool, animatable: Bool) {
self.isEnabled = enable
if animatable {
SPAnimation.animate(0.3, animations: {
self.alpha = enable ? 1 : 0.6
})
} else {
self.alpha = enable ? 1 : 0.6
}
}
}
@@ -71,8 +71,8 @@ public class SPDotButton: SPButton {
override public func sizeToFit() {
super.sizeToFit()
self.setWidth(self.customSideSize)
self.setHeight(self.customSideSize)
self.frame.set(width: self.customSideSize)
self.frame.set(height: self.customSideSize)
self.layoutSubviews()
}
@@ -87,9 +87,9 @@ public class SPDotButton: SPButton {
var currentXPosition: CGFloat = insest
for dotView in self.dotsView {
dotView.setWidth(sideSize)
dotView.setHeight(sideSize)
dotView.setYCenteringFromSuperview()
dotView.frame.set(width: sideSize)
dotView.frame.set(height: sideSize)
dotView.setYCenter()
dotView.frame.origin.x = currentXPosition
dotView.round()
currentXPosition += (sideSize + space)
@@ -44,7 +44,7 @@ public class SPNativeLargeButton: SPDownloadingButton {
override public func commonInit() {
super.commonInit()
self.titleLabel?.font = UIFont.system(type: UIFont.BoldType.DemiBold, size: 16)
self.titleLabel?.font = UIFont.system(weight: UIFont.FontWeight.demiBold, size: 16)
self.setTitleColor(UIColor.white)
self.backgroundColor = SPNativeColors.blue
self.layer.masksToBounds = true
@@ -58,13 +58,13 @@ public class SPNativeLargeButton: SPDownloadingButton {
let sideSpace: CGFloat = superview.frame.width * 0.112
var width = superview.frame.width - sideSpace * 2
width.setIfMore(when: 335)
self.setWidth(width)
self.frame.set(width: width)
}
}
override public func layoutSubviews() {
super.layoutSubviews()
self.gradientView?.setEqualsBoundsFromSuperview()
self.gradientView?.setSuperviewBounds()
self.gradientView?.layer.cornerRadius = self.layer.cornerRadius
self.gradientView?.gradientLayer.cornerRadius = self.layer.cornerRadius
}
@@ -62,7 +62,7 @@ public class SPPlayCircleButton: UIButton {
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: 0.45, withHeightFactor: 0.45, withCentering: true)
self.iconView.setBounds(self, withWidthFactor: 0.45, withHeightFactor: 0.45, withCentering: true)
self.round()
}
@@ -81,7 +81,7 @@ public class SPSocialButton: UIButton {
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
self.iconView.setBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
self.round()
}
}
@@ -21,15 +21,16 @@
import UIKit
public class SPSystemIconButton: UIButton {
public class SPSystemIconButton: SPButton {
let iconView = SPSystemIconView.init()
var widthIconFactor: CGFloat = 1
var heightIconFactor: CGFloat = 1
var type: SPSystemIconType {
var icon: SPSystemIcon {
didSet {
self.iconView.type = self.type
self.iconView.icon = self.icon
}
}
@@ -49,17 +50,17 @@ public class SPSystemIconButton: UIButton {
}
}
init() {
self.type = .share
super.init(frame: CGRect.zero)
override init() {
self.icon = .share
super.init()
self.commonInit()
}
init(type: SPSystemIconType) {
self.type = type
super.init(frame: CGRect.zero)
self.iconView.type = self.type
self.type = type
init(type: SPSystemIcon) {
self.icon = type
super.init()
self.iconView.icon = self.icon
self.icon = type
self.commonInit()
}
@@ -67,13 +68,14 @@ public class SPSystemIconButton: UIButton {
fatalError("init(coder:) has not been implemented")
}
fileprivate func commonInit() {
override func commonInit() {
super.commonInit()
self.iconView.isUserInteractionEnabled = false
self.addSubview(self.iconView)
}
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
self.iconView.setBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
}
}
@@ -23,7 +23,7 @@ import UIKit
class SPSystemIconView: UIView {
var type: SPSystemIconType {
var icon: SPSystemIcon {
didSet {
self.setNeedsDisplay()
}
@@ -36,13 +36,13 @@ class SPSystemIconView: UIView {
}
init() {
self.type = .share
self.icon = .share
super.init(frame: CGRect.zero)
self.commonInit()
}
init(type: SPSystemIconType) {
self.type = type
init(type: SPSystemIcon) {
self.icon = type
super.init(frame: CGRect.zero)
self.commonInit()
}
@@ -57,7 +57,7 @@ class SPSystemIconView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
switch type {
switch icon {
case .share:
SPCodeDraw.SystemIconPack.drawShare(frame: rect, resizing: .aspectFit, color: self.color)
break
@@ -125,7 +125,7 @@ public class SPMengTransformCollectionViewCell: SPCollectionViewCell {
self.titleLabel.text = ""
self.titleLabel.setDeepShadowForLetters()
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.titleLabel.font = UIFont.system(type: .DemiBold, size: 32)
self.titleLabel.font = UIFont.system(weight: .demiBold, size: 32)
self.titleLabel.textColor = UIColor.white
self.titleLabel.numberOfLines = 0
contentView.addSubview(self.titleLabel)
@@ -140,7 +140,7 @@ public class SPMengTransformCollectionViewCell: SPCollectionViewCell {
self.subtitleLabel.text = ""
self.subtitleLabel.setDeepShadowForLetters()
self.subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
self.subtitleLabel.font = UIFont.system(type: .Regular, size: 17)
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 17)
self.subtitleLabel.textColor = UIColor.white
self.subtitleLabel.numberOfLines = 0
contentView.addSubview(self.subtitleLabel)
@@ -53,6 +53,10 @@ public class SPCollectionView: UICollectionView {
func height(rows: Int) -> CGFloat {
return self.layout.itemSize.height * CGFloat(rows) + self.layout.minimumLineSpacing * CGFloat(rows - 1)
}
func width(columns: Int) -> CGFloat {
return self.layout.itemSize.width * CGFloat(columns) + self.layout.minimumInteritemSpacing * CGFloat(columns - 1)
}
}
//MARK: - Cache
@@ -23,12 +23,16 @@ import UIKit
public class SPController: SPStatusBarManagerController {
let emptyTitlesView = SPEmptyTitlesView(title: "No Data", subtitle: "No data or information")
let emptyTitlesView = SPEmptyLabelsView(title: "No Data", subtitle: "No data or information")
override public func viewDidLoad() {
super.viewDidLoad()
self.emptyTitlesView.isHidden = true
self.view.addSubview(self.emptyTitlesView)
}
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.updateLayout(with: self.view.frame.size)
}
@@ -39,12 +43,6 @@ public class SPController: SPStatusBarManagerController {
}, completion: nil)
}
@available(iOS 11.0, *)
override public func viewLayoutMarginsDidChange() {
super.viewLayoutMarginsDidChange()
self.updateLayout(with: self.view.frame.size)
}
func updateLayout(with size: CGSize) {
self.emptyTitlesView.layout(centerY: size.height / 2)
}
@@ -77,8 +77,6 @@ public class SPNativeTableController: SPTableController {
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.color = SPNativeColors.gray
self.view.addSubview(self.activityIndicatorView)
self.updateLayout(with: self.view.frame.size)
}
override public func numberOfSections(in tableView: UITableView) -> Int {
@@ -31,6 +31,10 @@ public class SPProposeController: SPController {
return 0.5
}
private var gradeFactor: CGFloat {
return 0.6
}
private var space: CGFloat {
return 6
}
@@ -75,8 +79,6 @@ public class SPProposeController: SPController {
if let image = self.data.image {
self.areaView.imageView.setImage(image: image, animatable: false)
}
self.updateLayout(with: self.view.frame.size)
}
override public func viewDidAppear(_ animated: Bool) {
@@ -92,7 +94,7 @@ public class SPProposeController: SPController {
self.areaView.frame.origin.y = self.view.frame.size.height
self.areaView.isHidden = false
SPAnimationSpring.animate(self.animationDuration, animations: {
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.6)
self.view.backgroundColor = UIColor.black.withAlphaComponent(self.gradeFactor)
self.areaView.frame.origin.y = self.view.frame.size.height - self.areaView.frame.height - (self.bottomSafeArea / 2) - self.space
}, spring: 1,
velocity: 1,
@@ -100,7 +102,6 @@ public class SPProposeController: SPController {
}
override public func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
let hide = {
self.view.backgroundColor = UIColor.black.withAlphaComponent(0)
self.areaView.frame.origin.y = self.view.frame.size.height
@@ -128,10 +129,8 @@ public class SPProposeController: SPController {
}
override func updateLayout(with size: CGSize) {
self.areaView.setWidth(size.width - (self.space * 2))
self.areaView.layoutSubviews()
self.areaView.sizeToFit()
self.areaView.frame.origin.x = self.space
super.updateLayout(with: size)
self.areaView.layout(origin: CGPoint.init(x: self.space, y: 0), width: size.width - (self.space * 2))
self.areaView.frame.origin.y = self.view.frame.size.height - self.areaView.frame.height - (self.bottomSafeArea / 2) - self.space
}
@@ -140,6 +139,7 @@ public class SPProposeController: SPController {
let returnAreaViewToPoint = {
SPAnimationSpring.animate(self.animationDuration, animations: {
self.areaView.frame.origin.y = self.view.frame.size.height - self.areaView.frame.height - (self.bottomSafeArea / 2) - self.space
self.view.backgroundColor = UIColor.black.withAlphaComponent(self.gradeFactor)
}, spring: 1,
velocity: 1,
options: .transitionCurlDown,
@@ -156,6 +156,13 @@ public class SPProposeController: SPController {
let translation = sender.translation(in: self.view)
self.areaView.center = CGPoint(x: areaView.center.x + 0, y: areaView.center.y + translation.y / 4)
sender.setTranslation(CGPoint.zero, in: self.view)
let baseY = self.view.frame.size.height - self.areaView.frame.height - (self.bottomSafeArea / 2) - self.space
let dem = -(baseY - self.areaView.frame.origin.y) / 6
var newGrade = self.gradeFactor - (dem / 100)
newGrade.setIfFewer(when: 0.2)
newGrade.setIfMore(when: self.gradeFactor + 0.05)
self.view.backgroundColor = UIColor.black.withAlphaComponent(newGrade)
case .ended:
returnAreaViewToPoint()
default:
@@ -179,10 +186,9 @@ public class SPProposeController: SPController {
let subtitleLabel = UILabel()
let imageView = SPDownloadingImageView()
let button = SPNativeLargeButton()
let closeButton = SPSystemIconButton(type: SPSystemIconType.close)
let closeButton = SPSystemIconButton(type: SPSystemIcon.close)
var imageSideSize: CGFloat = 160
private let space: CGFloat = 36
init() {
@@ -191,18 +197,18 @@ public class SPProposeController: SPController {
self.layer.masksToBounds = true
self.layer.cornerRadius = 34
self.titleLabel.font = UIFont.system(type: .Regular, size: 28)
self.titleLabel.font = UIFont.system(weight: .regular, size: 28)
self.titleLabel.textColor = UIColor.init(hex: "939393")
self.titleLabel.numberOfLines = 1
self.titleLabel.adjustsFontSizeToFitWidth = true
self.titleLabel.minimumScaleFactor = 0.5
self.titleLabel.setCenteringAlignment()
self.titleLabel.setCenterAlignment()
self.addSubview(self.titleLabel)
self.subtitleLabel.font = UIFont.system(type: .Regular, size: 16)
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 16)
self.subtitleLabel.textColor = SPNativeColors.black
self.subtitleLabel.numberOfLines = 0
self.subtitleLabel.setCenteringAlignment()
self.subtitleLabel.setCenterAlignment()
self.addSubview(self.subtitleLabel)
self.imageView.gradeView.backgroundColor = UIColor.white
@@ -210,15 +216,16 @@ public class SPProposeController: SPController {
self.imageView.layer.masksToBounds = true
self.addSubview(self.imageView)
self.button.titleLabel?.font = UIFont.system(type: UIFont.BoldType.Medium, size: 15)
self.button.titleLabel?.font = UIFont.system(weight: UIFont.FontWeight.medium, size: 15)
self.button.setTitleColor(SPNativeColors.black)
self.button.backgroundColor = UIColor.init(hex: "D4D3DB")
self.button.layer.cornerRadius = 13
self.button.backgroundColor = SPNativeColors.lightGray
self.addSubview(self.button)
self.closeButton.widthIconFactor = 0.4
self.closeButton.heightIconFactor = 0.4
self.closeButton.backgroundColor = UIColor.init(hex: "EFEFF4")
self.closeButton.color = UIColor.init(hex: "979797")
self.closeButton.backgroundColor = SPNativeColors.lightGray.withAlphaComponent(0.6)
self.closeButton.color = UIColor.init(hex: "979797")
self.addSubview(self.closeButton)
}
@@ -230,36 +237,40 @@ public class SPProposeController: SPController {
super.layoutSubviews()
self.titleLabel.sizeToFit()
self.titleLabel.frame.origin.y = self.space * 0.8
self.titleLabel.setWidth(self.frame.width - self.space * 3)
self.titleLabel.setXCenteringFromSuperview()
self.titleLabel.frame.origin.y = self.space * 0.9
self.titleLabel.frame.set(width: self.frame.width - self.space * 3)
self.titleLabel.setXCenter()
self.subtitleLabel.sizeToFit()
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomYPosition + 8
self.subtitleLabel.setWidth(self.frame.width - self.space * 2)
self.subtitleLabel.setXCenteringFromSuperview()
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomY + 8
self.subtitleLabel.frame.set(width: self.frame.width - self.space * 2)
self.subtitleLabel.setXCenter()
self.imageView.frame = CGRect.init(
x: 0, y: self.subtitleLabel.frame.bottomYPosition + self.space / 2,
x: 0, y: self.subtitleLabel.frame.bottomY + self.space / 2,
width: self.imageSideSize,
height: self.imageSideSize
)
self.imageView.setXCenteringFromSuperview()
self.imageView.setXCenter()
self.button.sizeToFit()
self.button.setWidth(self.frame.width - self.space * 2)
self.button.frame.origin.y = self.imageView.frame.bottomYPosition + self.space / 2
self.button.setXCenteringFromSuperview()
self.button.frame.set(height: 52)
self.button.frame.set(width: self.frame.width - self.space * 2)
self.button.frame.origin.y = self.imageView.frame.bottomY + self.space / 1.8
self.button.setXCenter()
self.closeButton.frame = CGRect.init(x: 0, y: 0, width: 24, height: 24)
self.closeButton.frame.origin.x = self.frame.width - self.closeButton.frame.width - 20
self.closeButton.frame.origin.y = 20
self.closeButton.round()
self.frame.set(height: self.button.frame.bottomY + self.space)
}
override func sizeToFit() {
super.sizeToFit()
self.setHeight(self.button.frame.bottomYPosition + self.space)
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.frame.set(width: width)
self.layoutSubviews()
}
}
@@ -31,7 +31,10 @@ public class SPTableController: SPStatusBarManagerTableController {
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.color = SPNativeColors.gray
self.view.addSubview(self.activityIndicatorView)
}
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.updateLayout(with: self.view.frame.size)
}
@@ -42,12 +45,6 @@ public class SPTableController: SPStatusBarManagerTableController {
}, completion: nil)
}
@available(iOS 11.0, *)
override public func viewLayoutMarginsDidChange() {
super.viewLayoutMarginsDidChange()
self.updateLayout(with: self.view.frame.size)
}
func updateLayout(with size: CGSize) {
self.activityIndicatorView.center = CGPoint.init(
x: size.width / 2,
@@ -0,0 +1,67 @@
// 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
public class SPCenterLabelsView: SPView {
let titleLabel = SPLabel()
let subtitleLabel = SPLabel()
override func commonInit() {
super.commonInit()
self.titleLabel.font = UIFont.system(weight: .bold, size: 33)
self.titleLabel.textAlignment = .center
self.titleLabel.textColor = UIColor.black
self.titleLabel.numberOfLines = 0
self.addSubview(self.titleLabel)
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 17)
self.subtitleLabel.textAlignment = .center
self.subtitleLabel.textColor = UIColor.black
self.subtitleLabel.numberOfLines = 0
self.addSubview(self.subtitleLabel)
}
func layout(x: CGFloat, y: CGFloat, width: CGFloat) {
self.frame.origin = CGPoint.init(x: x, y: y)
self.frame.set(width: width)
self.layoutSubviews()
}
override public func layoutSubviews() {
super.layoutSubviews()
self.titleLabel.frame.set(width: self.frame.width)
self.titleLabel.sizeToFit()
self.titleLabel.frame.set(width: self.frame.width)
self.titleLabel.frame.origin = CGPoint.zero
self.subtitleLabel.frame.set(width: self.frame.width)
self.subtitleLabel.sizeToFit()
self.subtitleLabel.frame.set(width: self.frame.width)
self.subtitleLabel.frame.origin.x = 0
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomY + 7
self.frame.set(height: self.subtitleLabel.frame.bottomY)
}
}
@@ -21,7 +21,7 @@
import UIKit
class SPEmptyTitlesView: SPView {
class SPEmptyLabelsView: SPView {
let titleLabel = UILabel()
let subtitleLabel = UILabel()
@@ -39,22 +39,22 @@ class SPEmptyTitlesView: SPView {
override func commonInit() {
super.commonInit()
self.titleLabel.font = UIFont.system(type: .Bold, size: 29)
self.titleLabel.font = UIFont.system(weight: .bold, size: 29)
self.titleLabel.textColor = SPNativeColors.gray
self.titleLabel.setCenteringAlignment()
self.titleLabel.setCenterAlignment()
self.titleLabel.numberOfLines = 0
self.addSubview(self.titleLabel)
self.subtitleLabel.font = UIFont.system(type: .Regular, size: 17)
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 17)
self.subtitleLabel.textColor = SPNativeColors.gray
self.subtitleLabel.setCenteringAlignment()
self.subtitleLabel.setCenterAlignment()
self.subtitleLabel.numberOfLines = 0
self.addSubview(self.subtitleLabel)
}
func layout(centerY: CGFloat) {
if let superview = self.superview {
self.setWidth(superview.frame.width * 0.7)
self.frame.set(width: superview.frame.width * 0.7)
self.layoutSubviews()
self.center = CGPoint.init(x: superview.frame.width / 2, y: centerY)
}
@@ -65,12 +65,12 @@ class SPEmptyTitlesView: SPView {
self.titleLabel.frame.origin = .zero
self.titleLabel.sizeToFit()
self.titleLabel.setWidth(self.frame.width)
self.titleLabel.frame.set(width: self.frame.width)
self.subtitleLabel.frame.origin = CGPoint.init(x: 0, y: self.titleLabel.frame.bottomYPosition + 5)
self.subtitleLabel.frame.origin = CGPoint.init(x: 0, y: self.titleLabel.frame.bottomY + 5)
self.subtitleLabel.sizeToFit()
self.subtitleLabel.setWidth(self.frame.width)
self.subtitleLabel.frame.set(width: self.frame.width)
self.setHeight(self.subtitleLabel.frame.bottomYPosition)
self.frame.set(height: self.subtitleLabel.frame.bottomY)
}
}
@@ -30,48 +30,49 @@ public class SPSectionLabelsView: SPView {
override func commonInit() {
super.commonInit()
self.titleLabel.font = UIFont.system(type: .Bold, size: 23)
self.titleLabel.font = UIFont.system(weight: .bold, size: 23)
self.titleLabel.textAlignment = .left
self.titleLabel.textColor = UIColor.black
self.titleLabel.numberOfLines = 0
self.addSubview(self.titleLabel)
self.subtitleLabel.font = UIFont.system(type: .Regular, size: 17)
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 17)
self.subtitleLabel.textAlignment = .left
self.subtitleLabel.textColor = UIColor.black.withAlphaComponent(0.7)
self.subtitleLabel.numberOfLines = 0
self.addSubview(self.subtitleLabel)
self.button.titleLabel?.font = UIFont.system(type: .Regular, size: 17)
self.button.titleLabel?.font = UIFont.system(weight: .regular, size: 17)
self.button.setTitleColor(SPNativeColors.blue, for: UIControl.State.normal)
self.addSubview(self.button)
}
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.setWidth(width)
self.frame.set(width: width)
self.layoutSubviews()
}
func layout(x: CGFloat, y: CGFloat, width: CGFloat) {
self.layout(origin: CGPoint.init(x: x, y: y), width: width)
}
override public func layoutSubviews() {
super.layoutSubviews()
self.titleLabel.sizeToFit()
self.titleLabel.setWidth(self.frame.width)
self.titleLabel.frame.set(width: self.frame.width)
self.titleLabel.frame.origin = CGPoint.zero
//self.titleLabel.backgroundColor = UIColor.lightGray
self.subtitleLabel.sizeToFit()
self.subtitleLabel.setWidth(self.frame.width)
self.subtitleLabel.frame.set(width: self.frame.width)
self.subtitleLabel.frame.origin.x = 0
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomYPosition + 3
//self.subtitleLabel.backgroundColor = UIColor.darkGray
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomY + 3
self.button.sizeToFit()
self.button.frame.bottomXPosition = self.frame.width
self.button.frame.bottomX = self.frame.width
self.button.center.y = self.titleLabel.center.y
//self.button.backgroundColor = UIColor.darkGray
self.setHeight(self.subtitleLabel.frame.bottomYPosition)
self.frame.set(height: self.subtitleLabel.frame.bottomY)
}
}
@@ -33,7 +33,7 @@ public class SPDownloadingImageView: SPImageView {
self.addSubview(self.gradeView)
self.gradeView.backgroundColor = UIColor.init(hex: "F0F1F6")
self.activityIndiactorView.color = UIColor.darkGray
self.addSubview(self.activityIndiactorView)
//self.addSubview(self.activityIndiactorView)
self.activityIndiactorView.startAnimating()
}
@@ -70,7 +70,7 @@ public class SPDownloadingImageView: SPImageView {
override public func layoutSubviews() {
super.layoutSubviews()
self.gradeView.setEqualsBoundsFromSuperview()
self.gradeView.setSuperviewBounds()
self.activityIndiactorView.center = CGPoint.init(x: self.bounds.midX, y: self.bounds.midY)
}
}
@@ -23,7 +23,7 @@ import UIKit
public class SPFakeBarView: UIView {
public var style: SPNavigationTitleStyle = . small {
public var style: SPNavigationTitleStyle = .small {
didSet {
self.updateStyle()
}
@@ -54,15 +54,15 @@ public class SPFakeBarView: UIView {
}
}
public var closeButton: closeButtonPlace = .none {
public var closeButtonPossition: CloseButtonPosition = .none {
didSet {
self.leftButton.titleLabel?.font = UIFont.system(type: .Regular, size: 17)
self.rightButton.titleLabel?.font = UIFont.system(type: .Regular, size: 17)
switch self.closeButton {
self.leftButton.titleLabel?.font = UIFont.system(weight: .regular, size: 17)
self.rightButton.titleLabel?.font = UIFont.system(weight: .regular, size: 17)
switch self.closeButtonPossition {
case .left:
self.leftButton.titleLabel?.font = UIFont.system(type: .DemiBold, size: 17)
self.leftButton.titleLabel?.font = UIFont.system(weight: .demiBold, size: 17)
case .right:
self.rightButton.titleLabel?.font = UIFont.system(type: .DemiBold, size: 17)
self.rightButton.titleLabel?.font = UIFont.system(weight: .demiBold, size: 17)
case .none:
break
}
@@ -121,7 +121,7 @@ public class SPFakeBarView: UIView {
self.addSubview(self.subtitleLabel)
self.subtitleLabel.textColor = UIColor.init(hex: "8E8E92")
self.subtitleLabel.font = UIFont.system(type: .DemiBold, size: 13)
self.subtitleLabel.font = UIFont.system(weight: .demiBold, size: 13)
self.subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
self.subtitleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 16).isActive = true
self.subtitleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16).isActive = true
@@ -129,7 +129,7 @@ public class SPFakeBarView: UIView {
self.leftButton.setTitleColor(self.elementsColor)
self.leftButton.titleLabel?.textAlignment = .left
self.leftButton.titleLabel?.font = UIFont.system(type: .DemiBold, size: 16)
self.leftButton.titleLabel?.font = UIFont.system(weight: .demiBold, size: 16)
self.leftButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 17, bottom: 0, right: 0)
self.addSubview(self.leftButton)
self.leftButton.translatesAutoresizingMaskIntoConstraints = false
@@ -138,14 +138,14 @@ public class SPFakeBarView: UIView {
self.rightButton.setTitleColor(self.elementsColor)
self.rightButton.titleLabel?.textAlignment = .right
self.rightButton.titleLabel?.font = UIFont.system(type: .DemiBold, size: 17)
self.rightButton.titleLabel?.font = UIFont.system(weight: .demiBold, size: 17)
self.rightButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16)
self.addSubview(self.rightButton)
self.rightButton.translatesAutoresizingMaskIntoConstraints = false
self.rightButton.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
self.rightButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -12).isActive = true
self.closeButton = .none
self.closeButtonPossition = .none
self.setContraints()
self.updateStyle()
@@ -185,14 +185,14 @@ public class SPFakeBarView: UIView {
self.titleBottomConstraint?.constant = -12
}
self.addStatusBarHeight = true
self.titleLabel.font = UIFont.system(type: .DemiBold, size: 17)
self.titleLabel.setCenteringAlignment()
self.titleLabel.font = UIFont.system(weight: .demiBold, size: 17)
self.titleLabel.setCenterAlignment()
case .stork:
self.height = 66
self.titleBottomConstraint?.constant = -12
self.addStatusBarHeight = false
self.titleLabel.font = UIFont.system(type: .DemiBold, size: 17)
self.titleLabel.setCenteringAlignment()
self.titleLabel.font = UIFont.system(weight: .demiBold, size: 17)
self.titleLabel.setCenterAlignment()
case .large:
if UIViewController.statusBarHeight == 44 {
self.height = 140 - 44
@@ -202,7 +202,7 @@ public class SPFakeBarView: UIView {
self.titleBottomConstraint?.constant = -4
}
self.addStatusBarHeight = true
self.titleLabel.font = UIFont.system(type: .Bold, size: 34)
self.titleLabel.font = UIFont.system(weight: .bold, size: 34)
self.titleLabel.textAlignment = .left
break
}
@@ -215,7 +215,7 @@ public class SPFakeBarView: UIView {
self.updateConstraints()
}
public enum closeButtonPlace {
public enum CloseButtonPosition {
case left
case right
case none
@@ -36,8 +36,7 @@ public class SPFooterActionsView: SPView {
func addButton(title: String, titleColor: UIColor, target: @escaping ()->()) {
let button = SPFooterActionButton()
button.setTitle(title)
button.setTitleColor(titleColor)
button.setTitle(title, color: titleColor)
button.target { target() }
self.buttons.append(button)
self.addSubview(button)
@@ -56,7 +55,7 @@ public class SPFooterActionsView: SPView {
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.setWidth(width)
self.frame.set(width: width)
self.layoutSubviews()
}
@@ -66,7 +65,7 @@ public class SPFooterActionsView: SPView {
self.sectionLabels.layout(origin: CGPoint.zero, width: self.frame.width)
let buttonHeight: CGFloat = 50
var yPositionButton: CGFloat = self.sectionLabels.frame.bottomYPosition + 12
var yPositionButton: CGFloat = self.sectionLabels.frame.bottomY + 12
if !self.buttons.isEmpty {
for i in 0...(buttons.count - 1) {
@@ -75,14 +74,14 @@ public class SPFooterActionsView: SPView {
separator.frame.origin.x = 0
separator.frame.origin.y = yPositionButton
separator.setWidth(self.frame.width)
separator.frame.set(width: self.frame.width)
button.frame = CGRect.init(x: 0, y: yPositionButton, width: self.frame.width, height: buttonHeight)
yPositionButton += buttonHeight
}
self.setHeight(yPositionButton)
self.frame.set(height: yPositionButton)
}
}
}
@@ -104,7 +103,7 @@ class SPFooterActionButton: SPButton {
override func commonInit() {
super.commonInit()
self.setTitleColor(SPNativeColors.blue)
self.titleLabel?.font = UIFont.system(type: .Regular, size: 21)
self.titleLabel?.font = UIFont.system(weight: .regular, size: 21)
self.contentHorizontalAlignment = .left
}
@@ -113,6 +112,6 @@ class SPFooterActionButton: SPButton {
let sideSize: CGFloat = self.frame.height * 0.36
self.rightIconView?.frame = CGRect.init(x: 0, y: 0, width: sideSize, height: sideSize)
self.rightIconView?.center.y = self.frame.height / 2
self.rightIconView?.frame.bottomXPosition = self.frame.width - sideSize / 3
self.rightIconView?.frame.bottomX = self.frame.width - sideSize / 3
}
}
@@ -47,7 +47,6 @@ public class SPScrollView: UIScrollView {
&& !(view is UISwitch) {
return true
}
return super.touchesShouldCancel(in: view)
}
}
@@ -31,16 +31,17 @@ class SPSeparatorView: SPView {
super.commonInit()
self.backgroundColor = UIColor.init(hex: "515B66").withAlphaComponent(0.25)
self.round = true
self.setHeight(self.height)
self.frame.set(height: self.height)
}
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = CGPoint.init(x: floor(origin.x), y: floor(origin.y))
self.set(width: floor(width), height: self.height)
self.frame.set(width: floor(width))
self.frame.set(height: self.height)
}
override func layoutSubviews() {
super.layoutSubviews()
self.setHeight(self.height)
self.frame.set(height: self.height)
}
}
@@ -52,6 +52,6 @@ class SPVideoPlayerView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
self.playerController.view.setEqualsBoundsFromSuperview()
self.playerController.view.setSuperviewBounds()
}
}
@@ -46,7 +46,7 @@ public class SPFormButtonTableViewCell: UITableViewCell {
self.button.setTitle("Button", for: .normal)
self.button.backgroundColor = UIColor.clear
self.button.setTitleColor(SPNativeColors.blue)
self.button.titleLabel?.font = UIFont.system(type: .Medium, size: 17)
self.button.titleLabel?.font = UIFont.system(weight: .medium, size: 17)
self.selectionStyle = .none
self.contentView.addSubview(self.button)
}
@@ -60,7 +60,7 @@ public class SPFormButtonTableViewCell: UITableViewCell {
override public func layoutSubviews() {
super.layoutSubviews()
self.button.setEqualsBoundsFromSuperview()
self.button.setSuperviewBounds()
switch self.separatorInsetStyle {
case .all:
@@ -30,10 +30,10 @@ public class SPFormFeaturedTitleTableViewCell: UITableViewCell {
didSet {
switch type {
case .large:
self.titleLabel.font = UIFont.system(type: .Bold, size: 22)
self.titleLabel.font = UIFont.system(weight: .bold, size: 22)
self.titleLabel.textColor = UIColor.black
case .smallColorful:
self.titleLabel.font = UIFont.system(type: .DemiBold, size: 11)
self.titleLabel.font = UIFont.system(weight: .demiBold, size: 11)
self.titleLabel.textColor = SPNativeColors.blue
self.titleLabel.text = self.titleLabel.text?.uppercased()
}
@@ -69,7 +69,7 @@ public class SPFormFeaturedTitleTableViewCell: UITableViewCell {
contentView.addSubview(self.titleLabel)
self.titleLabel.numberOfLines = 0
self.titleLabel.text = "Title"
self.titleLabel.font = UIFont.system(type: .Bold, size: 21)
self.titleLabel.font = UIFont.system(weight: .bold, size: 21)
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.titleLabel.setLettersSpacing(-0.24)
@@ -83,7 +83,7 @@ public class SPFormFeaturedTitleTableViewCell: UITableViewCell {
self.withButton = false
self.button.setTitle("Button Title", for: UIControl.State.normal)
self.button.setTitleColor(SPNativeColors.blue)
self.button.titleLabel?.font = UIFont.system(type: .Medium, size: 17)
self.button.titleLabel?.font = UIFont.system(weight: .medium, size: 17)
self.button.translatesAutoresizingMaskIntoConstraints = false
self.button.titleLabel?.textAlignment = .right
contentView.addSubview(self.button)
@@ -58,13 +58,13 @@ public class SPFormLabelTableViewCell: SPTableViewCell {
self.label.textAlignment = .left
self.label.text = "Title"
self.label.numberOfLines = 1
self.label.font = UIFont.system(type: .Regular, size: 17)
self.label.font = UIFont.system(weight: .regular, size: 17)
self.contentView.addSubview(self.label)
self.descriptionLabel.textAlignment = .right
self.descriptionLabel.text = "Description"
self.descriptionLabel.numberOfLines = 1
self.descriptionLabel.font = UIFont.system(type: .Regular, size: 17)
self.descriptionLabel.font = UIFont.system(weight: .regular, size: 17)
self.descriptionLabel.textColor = SPNativeColors.gray
self.contentView.addSubview(self.descriptionLabel)
@@ -87,7 +87,7 @@ public class SPFormLabelTableViewCell: SPTableViewCell {
override public func layoutSubviews() {
super.layoutSubviews()
let xPosition: CGFloat = (self.imageView?.frame.bottomXPosition ?? 0) + self.layoutMargins.left
let xPosition: CGFloat = (self.imageView?.frame.bottomX ?? 0) + self.layoutMargins.left
var labelWidth: CGFloat = self.contentView.frame.width * 0.45
if let width = self.fixWidthLabel {
@@ -101,9 +101,9 @@ public class SPFormLabelTableViewCell: SPTableViewCell {
let space: CGFloat = 15
self.descriptionLabel.frame = CGRect.init(
x: self.label.frame.bottomXPosition + space,
x: self.label.frame.bottomX + space,
y: 0,
width: self.contentView.frame.width - self.label.frame.bottomXPosition -
width: self.contentView.frame.width - self.label.frame.bottomX -
self.contentView.layoutMargins.right - space,
height: self.contentView.frame.height)
@@ -119,7 +119,7 @@ public class SPFormLabelTableViewCell: SPTableViewCell {
self.separatorInset.left = 0
case .beforeImage:
if let imageView = self.imageView {
self.separatorInset.left = imageView.frame.bottomYPosition + self.layoutMargins.left
self.separatorInset.left = imageView.frame.bottomY + self.layoutMargins.left
} else {
self.separatorInset.left = 0
}
@@ -60,10 +60,10 @@ public class SPFormTextFiledTableViewCell: UITableViewCell {
self.backgroundColor = UIColor.white
self.label.text = "Label"
self.label.font = UIFont.system(type: .Regular, size: 17)
self.label.font = UIFont.system(weight: .regular, size: 17)
self.contentView.addSubview(self.label)
self.textField.font = UIFont.system(type: .Regular, size: 17)
self.textField.font = UIFont.system(weight: .regular, size: 17)
self.textField.placeholder = "Placeholder"
self.contentView.addSubview(self.textField)
@@ -79,7 +79,7 @@ public class SPFormTextFiledTableViewCell: UITableViewCell {
}
self.label.frame = CGRect.init(x: self.layoutMargins.left, y: 0, width: labelWidth, height: self.contentView.frame.height)
let space: CGFloat = 15
self.textField.frame = CGRect.init(x: self.label.frame.bottomXPosition + space, y: 0, width: self.contentView.frame.width - self.label.frame.bottomXPosition - self.layoutMargins.right - space, height: self.contentView.frame.height)
self.textField.frame = CGRect.init(x: self.label.frame.bottomX + space, y: 0, width: self.contentView.frame.width - self.label.frame.bottomX - self.layoutMargins.right - space, height: self.contentView.frame.height)
switch self.separatorInsetStyle {
case .all:
@@ -61,7 +61,7 @@ public class SPFormTextInputTableViewCell: SPTableViewCell {
self.backgroundColor = UIColor.white
self.textInputView.textAlignment = .left
self.textInputView.text = ""
self.textInputView.font = UIFont.system(type: .Regular, size: 17)
self.textInputView.font = UIFont.system(weight: .regular, size: 17)
self.textInputView.translatesAutoresizingMaskIntoConstraints = false
self.textInputView.showsVerticalScrollIndicator = false
self.contentView.addSubview(self.textInputView)
@@ -90,7 +90,7 @@ public class SPFormTextInputTableViewCell: SPTableViewCell {
override public func layoutSubviews() {
super.layoutSubviews()
let xPosition: CGFloat = (self.imageView?.frame.bottomXPosition ?? 0) + self.layoutMargins.left
let xPosition: CGFloat = (self.imageView?.frame.bottomX ?? 0) + self.layoutMargins.left
self.textInputView.frame = CGRect.init(
x: xPosition, y: 0,
@@ -103,7 +103,7 @@ public class SPFormTextInputTableViewCell: SPTableViewCell {
self.separatorInset.left = 0
case .beforeImage:
if let imageView = self.imageView {
self.separatorInset.left = imageView.frame.bottomYPosition + self.layoutMargins.left
self.separatorInset.left = imageView.frame.bottomY + self.layoutMargins.left
} else {
self.separatorInset.left = 0
}
@@ -214,7 +214,7 @@ public class SPBaseContentTableViewCell: SPTableViewCell {
//titleLabel
self.titleLabel.numberOfLines = 0
self.titleLabel.font = UIFont.system(type: UIFont.BoldType.Medium, size: 17)
self.titleLabel.font = UIFont.system(weight: UIFont.FontWeight.medium, size: 17)
self.titleLabel.textAlignment = .left
self.titleLabel.textColor = UIColor.black
self.contentView.addSubview(self.titleLabel)
@@ -234,7 +234,7 @@ public class SPBaseContentTableViewCell: SPTableViewCell {
//subtitleLabel
self.subtitleLabel.numberOfLines = 0
self.subtitleLabel.font = UIFont.system(type: UIFont.BoldType.Regular, size: 15)
self.subtitleLabel.font = UIFont.system(weight: UIFont.FontWeight.regular, size: 15)
self.subtitleLabel.textAlignment = .left
self.subtitleLabel.textColor = UIColor.black
self.contentView.addSubview(self.subtitleLabel)
@@ -248,7 +248,7 @@ public class SPBaseContentTableViewCell: SPTableViewCell {
//descriptionLabel
self.descriptionLabel.numberOfLines = 0
self.descriptionLabel.font = UIFont.system(type: UIFont.BoldType.Regular, size: 15)
self.descriptionLabel.font = UIFont.system(weight: UIFont.FontWeight.regular, size: 15)
self.descriptionLabel.textAlignment = .left
self.descriptionLabel.textColor = SPNativeColors.gray
self.contentView.addSubview(self.descriptionLabel)
@@ -295,15 +295,15 @@ public class SPBaseContentTableViewCell: SPTableViewCell {
self.iconImageView.setNative()
self.titleLabel.text = "Title"
self.titleLabel.font = UIFont.system(type: UIFont.BoldType.Medium, size: 17)
self.titleLabel.font = UIFont.system(weight: UIFont.FontWeight.medium, size: 17)
self.titleLabel.textAlignment = .left
self.titleLabel.textColor = UIColor.black
self.subtitleLabel.text = "Subtitle"
self.subtitleLabel.font = UIFont.system(type: UIFont.BoldType.Regular, size: 15)
self.subtitleLabel.font = UIFont.system(weight: UIFont.FontWeight.regular, size: 15)
self.subtitleLabel.textAlignment = .left
self.subtitleLabel.textColor = UIColor.black
self.descriptionLabel.text = "Description"
self.descriptionLabel.font = UIFont.system(type: UIFont.BoldType.Regular, size: 15)
self.descriptionLabel.font = UIFont.system(weight: UIFont.FontWeight.regular, size: 15)
self.descriptionLabel.textAlignment = .left
self.descriptionLabel.textColor = SPNativeColors.gray
self.button.setTitle("Button")
@@ -63,7 +63,7 @@ public class SPImageTableViewCell: SPTableViewCell {
let marginGuide = contentView.layoutMarginsGuide
self.titleLabel.numberOfLines = 0
self.titleLabel.font = UIFont.system(type: UIFont.BoldType.Medium, size: 21)
self.titleLabel.font = UIFont.system(weight: UIFont.FontWeight.medium, size: 21)
self.titleLabel.textAlignment = .left
self.titleLabel.textColor = UIColor.black
self.contentView.addSubview(self.titleLabel)
@@ -77,7 +77,7 @@ public class SPImageTableViewCell: SPTableViewCell {
self.titleLabelTopConstraint.isActive = true
self.subtitleLabel.numberOfLines = 3
self.subtitleLabel.font = UIFont.system(type: UIFont.BoldType.Regular, size: 15)
self.subtitleLabel.font = UIFont.system(weight: UIFont.FontWeight.regular, size: 15)
self.subtitleLabel.textAlignment = .left
self.subtitleLabel.textColor = SPNativeColors.gray
self.contentView.addSubview(self.subtitleLabel)
@@ -115,7 +115,7 @@ public class SPImageTableViewCell: SPTableViewCell {
override public func layoutSubviews() {
super.layoutSubviews()
self.accessoryView?.center.y = self.titleLabel.frame.bottomYPosition + self.subtitleLabel.frame.height / 2
self.accessoryView?.center.y = self.titleLabel.frame.bottomY + self.subtitleLabel.frame.height / 2
if self.accessoryView?.frame.origin.y ?? 0 < 5 {
self.accessoryView?.center.y = self.frame.height / 2
}
@@ -49,10 +49,10 @@ public class SPPromoTableViewCell: SPBaseContentTableViewCell {
self.spaceAfterDescribtion = 16
self.bottomSpace = 22
self.titleLabel.font = UIFont.system(type: .DemiBold, size: 16)
self.titleLabel.setCenteringAlignment()
self.descriptionLabel.font = UIFont.system(type: .Regular, size: 13)
self.descriptionLabel.setCenteringAlignment()
self.titleLabel.font = UIFont.system(weight: .demiBold, size: 16)
self.titleLabel.setCenterAlignment()
self.descriptionLabel.font = UIFont.system(weight: .regular, size: 13)
self.descriptionLabel.setCenterAlignment()
self.subtitleLabel.textColor = UIColor.lightGray
self.button.style = .main
}
@@ -35,7 +35,7 @@ public class SPProposeTableViewCell: UITableViewCell {
self.addSubview(self.button)
self.button.setTitle("Action", for: .normal)
self.button.titleLabel?.font = UIFont.system(type: .DemiBold, size: 14)
self.button.titleLabel?.font = UIFont.system(weight: .demiBold, size: 14)
self.button.titleLabel?.numberOfLines = 0
self.button.secondColor = SPNativeColors.blue
self.button.baseColor = UIColor.white
@@ -48,9 +48,9 @@ public class SPProposeTableViewCell: UITableViewCell {
self.addSubview(self.titleLabel)
self.titleLabel.numberOfLines = 0
self.titleLabel.setCenteringAlignment()
self.titleLabel.setCenterAlignment()
self.titleLabel.textAlignment = .left
self.titleLabel.font = UIFont.system(type: .Regular, size: 16)
self.titleLabel.font = UIFont.system(weight: .regular, size: 16)
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.titleLabel.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor).isActive = true
self.titleLabel.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 0).isActive = true
@@ -21,9 +21,7 @@
import UIKit
public struct SPVibration { private init() {} }
extension SPVibration {
public struct SPVibration {
public static func impact(_ style: Style) {
@@ -57,4 +55,6 @@ extension SPVibration {
case success
case warning
}
private init() {}
}
@@ -18,8 +18,6 @@ class ModalTableViewController: UIViewController {
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.tableView.contentInset.top = self.navBar.height
self.tableView.scrollIndicatorInsets.top = self.navBar.height
self.tableView.contentInset.bottom = self.safeArea.bottom
self.tableView.scrollIndicatorInsets.bottom = self.safeArea.bottom
self.view.addSubview(self.tableView)
self.navBar.titleLabel.text = "Table"
@@ -30,21 +28,13 @@ class ModalTableViewController: UIViewController {
self.updateLayout(with: self.view.frame.size)
}
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (contex) in
self.updateLayout(with: size)
}, completion: nil)
}
@available(iOS 11.0, *)
override public func viewLayoutMarginsDidChange() {
super.viewLayoutMarginsDidChange()
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.updateLayout(with: self.view.frame.size)
}
func updateLayout(with size: CGSize) {
self.tableView.frame = CGRect.init(origin: CGPoint.zero, size: size)
self.tableView.frame = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
}
@objc func dismissAction() {
+29 -16
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) {
@@ -178,17 +193,22 @@ func scrollViewDidScroll(_ scrollView: UIScrollView) {
Working with a collections classes is not difficult. In the `Example` folder you can find an implementation. However, I will give a couple of tips for making the table look better.
Firstly, if you use `SPFakeBarView`, don't forget to set top insets for content & scroll indicator. Also, I recommend setting bottom insets:
Firstly, if you use `SPFakeBarView`, don't forget to set top insets for content & scroll indicator. Also, I recommend setting bottom insets (it optional):
```swift
tableView.contentInset.top = self.navBar.height
tableView.scrollIndicatorInsets.top = self.navBar.height
tableView.contentInset.bottom = self.safeAreaInsets.bottom
tableView.scrollIndicatorInsets.bottom = self.safeAreaInsets.bottom
```
Please, also use `SPStorkController.scrollViewDidScroll()` function in delegate for more interactiveness with your collection or table view
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
@@ -209,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.
+5 -4
View File
@@ -1,6 +1,7 @@
Pod::Spec.new do |s|
s.name = "SPStorkController"
s.version = "1.4.4"
s.version = "1.6"
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 }
@@ -8,11 +9,11 @@ Pod::Spec.new do |s|
s.author = { "Ivan Vorobei" => "hello@ivanvorobei.by" }
s.swift_version = '4.2'
s.swift_version = '4.2', '5.0'
s.platform = :ios
s.ios.framework = 'UIKit'
s.ios.deployment_target = "10.0"
s.source_files = "Source/SPStorkController/**/*.swift"
end
end
@@ -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?, showIndicator: Bool, hideIndicatorWhenScroll: Bool, showCloseButton: Bool, complection: (() -> Void)?) {
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()
}
+22 -1
View File
@@ -28,19 +28,40 @@ public struct SPStorkController {
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)
}
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)
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,15 +68,18 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
override var frameOfPresentedViewInContainerView: CGRect {
guard let containerView = containerView else { return .zero }
let baseY: CGFloat = self.topSpace + 13
let maxHeight: CGFloat = containerView.bounds.height - baseY
var height: CGFloat = maxHeight
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")
if let customHeight = self.customHeight {
if customHeight < maxHeight {
height = customHeight
} else {
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
return CGRect(x: 0, y: yOffset, width: containerView.bounds.width, height: containerView.bounds.height - yOffset)
return CGRect(x: 0, y: containerView.bounds.height - height, width: containerView.bounds.width, height: height)
}
override func presentationTransitionWillBegin() {
@@ -95,6 +98,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)
@@ -135,8 +144,9 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
containerView.insertSubview(snapshotView, aboveSubview: self.backgroundView)
snapshotView.frame = initialFrame
snapshotView.transform = transformForSnapshotView
snapshotView.alpha = self.alpha
snapshotView.alpha = 1 - self.alpha
snapshotView.layer.cornerRadius = self.cornerRadius
snapshotView.contentMode = .top
snapshotView.layer.masksToBounds = true
rootSnapshotView = snapshotView
@@ -189,7 +199,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() {
@@ -227,6 +239,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
containerView.insertSubview(snapshotView, aboveSubview: backgroundView)
snapshotView.frame = initialFrame
snapshotView.transform = initialTransform
snapshotView.contentMode = .top
rootSnapshotView = snapshotView
snapshotView.layer.cornerRadius = self.cornerRadius
snapshotView.layer.masksToBounds = true
@@ -234,7 +247,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
let snapshotRoundedView = UIView()
snapshotRoundedView.layer.cornerRadius = self.cornerRadius
snapshotRoundedView.layer.masksToBounds = true
snapshotRoundedView.backgroundColor = UIColor.black.withAlphaComponent(1 - self.alpha)
snapshotRoundedView.backgroundColor = UIColor.black.withAlphaComponent(self.alpha)
containerView.insertSubview(snapshotRoundedView, aboveSubview: snapshotView)
snapshotRoundedView.frame = initialFrame
snapshotRoundedView.transform = initialTransform
@@ -260,6 +273,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
@@ -292,7 +307,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(
@@ -323,6 +340,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.18, animations: {
self.indicatorView.alpha = newAlpha
})
}
private func updatePresentedViewForTranslation(inVerticalDirection translation: CGFloat) {
if self.startDismissing { return }
@@ -342,9 +374,12 @@ 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
}
}
}
@@ -367,6 +402,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()
@@ -381,6 +417,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,21 +25,14 @@ final class SPStorkPresentingAnimationController: NSObject, UIViewControllerAnim
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let presentedViewController = transitionContext.viewController(forKey: .to) else {
return
}
guard let presentedViewController = transitionContext.viewController(forKey: .to) else { return }
let containerView = transitionContext.containerView
containerView.addSubview(presentedViewController.view)
//presentedViewController.view.frame = CGRect(x: 0, y: containerView.bounds.height, width: containerView.bounds.width, height: containerView.bounds.height)
let finalFrameForPresentedView = transitionContext.finalFrame(for: presentedViewController)
// NEW FRAMING: Testing now. Maybe correct. If remove it lines, init frame of controller will be equal container (not stork)
presentedViewController.view.frame = finalFrameForPresentedView
presentedViewController.view.frame.origin.y = containerView.bounds.height
// END NEW.
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
@@ -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)
}
}