Commit 95bee682 by Daniel Dahan

initial SideNavigationViewController prototype

parent 6224b1aa
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'MK' s.name = 'MK'
s.version = '1.23.0' s.version = '1.22.0'
s.license = { :type => "AGPLv3+", :file => "LICENSE" } s.license = { :type => "AGPLv3+", :file => "LICENSE" }
s.summary = 'A Material Design Framework In Swift' s.summary = 'A Material Design Framework In Swift'
s.homepage = 'http://materialkit.io' s.homepage = 'http://materialkit.io'
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.23.0</string> <string>1.22.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
......
...@@ -67,10 +67,11 @@ public struct MaterialAnimation { ...@@ -67,10 +67,11 @@ public struct MaterialAnimation {
/** /**
:name: animationWithDuration :name: animationWithDuration
*/ */
public static func animationWithDuration(duration: CFTimeInterval, animations: (() -> Void), completion: (() -> Void)? = nil) { public static func animationWithDuration(duration: CFTimeInterval, animations: (() -> Void), options: UIViewAnimationOptions? = nil, completion: (() -> Void)? = nil) {
CATransaction.begin() CATransaction.begin()
CATransaction.setAnimationDuration(duration) CATransaction.setAnimationDuration(duration)
CATransaction.setCompletionBlock(completion) CATransaction.setCompletionBlock(completion)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut))
animations() animations()
CATransaction.commit() CATransaction.commit()
} }
......
...@@ -521,9 +521,8 @@ public class MaterialCollectionViewCell : UICollectionViewCell, UIGestureRecogni ...@@ -521,9 +521,8 @@ public class MaterialCollectionViewCell : UICollectionViewCell, UIGestureRecogni
} else if rightOnDragRelease { } else if rightOnDragRelease {
delegate?.materialCollectionViewCellDidCloseRightLayer?(self) delegate?.materialCollectionViewCellDidCloseRightLayer?(self)
} }
default: default:break
break
} }
} }
......
...@@ -34,74 +34,23 @@ public extension UIViewController { ...@@ -34,74 +34,23 @@ public extension UIViewController {
} }
} }
public enum SideNavigationViewState {
case Opened
case Closed
}
@objc(SideNavigationViewContainer)
public class SideNavigationViewContainer : NSObject {
/**
:name: state
*/
public private(set) var state: SideNavigationViewState
/**
:name: point
*/
public private(set) var point: CGPoint
/**
:name: frame
*/
public private(set) var frame: CGRect
/**
:name: description
*/
public override var description: String {
let s: String = .Opened == state ? "Opened" : "Closed"
return "(state: \(s), point: \(point), frame: \(frame))"
}
/**
:name: init
*/
public init(state: SideNavigationViewState, point: CGPoint, frame: CGRect) {
self.state = state
self.point = point
self.frame = frame
}
}
@objc(SideNavigationViewDelegate)
public protocol SideNavigationViewDelegate {
// left
optional func sideNavDidBeginLeftPan(nav: SideNavigationViewController, container: SideNavigationViewContainer)
optional func sideNavDidChangeLeftPan(nav: SideNavigationViewController, container: SideNavigationViewContainer)
optional func sideNavDidEndLeftPan(nav: SideNavigationViewController, container: SideNavigationViewContainer)
optional func sideNavDidOpenLeftViewContainer(nav: SideNavigationViewController, container: SideNavigationViewContainer)
optional func sideNavDidCloseLeftViewContainer(nav: SideNavigationViewController, container: SideNavigationViewContainer)
optional func sideNavDidTapLeft(nav: SideNavigationViewController, container: SideNavigationViewContainer)
}
@objc(SideNavigationViewController) @objc(SideNavigationViewController)
public class SideNavigationViewController: UIViewController, UIGestureRecognizerDelegate { public class SideNavigationViewController: UIViewController, UIGestureRecognizerDelegate {
/** /**
:name: default options :name: default options
*/ */
public struct defaultOptions { public struct defaultOptions {
public static var bezelWidth: CGFloat = 48 public static var bezelWidth: CGFloat = 48
public static var bezelHeight: CGFloat = 48 public static var bezelHeight: CGFloat = 48
public static var containerWidth: CGFloat = 240 public static var containerWidth: CGFloat = 240
public static var containerHeight: CGFloat = 240 public static var containerHeight: CGFloat = 240
public static var defaultAnimationDuration: CGFloat = 0.3 public static var defaultAnimationDuration: CGFloat = 0.25
public static var threshold: CGFloat = 48 public static var threshold: CGFloat = 48
public static var panningEnabled: Bool = true public static var panningEnabled: Bool = true
} }
/** /**
:name: options :name: options
*/ */
public struct options { public struct options {
public static var shadowOpacity: Float = 0 public static var shadowOpacity: Float = 0
...@@ -120,19 +69,14 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -120,19 +69,14 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
/** /**
:name: delegate :name: isViewBasedAppearance
*/
public weak var delegate: SideNavigationViewDelegate?
/**
:name: isViewBasedAppearance
*/ */
public var isViewBasedAppearance: Bool { public var isViewBasedAppearance: Bool {
return 0 == NSBundle.mainBundle().objectForInfoDictionaryKey("UIViewControllerBasedStatusBarAppearance") as? Int return 0 == NSBundle.mainBundle().objectForInfoDictionaryKey("UIViewControllerBasedStatusBarAppearance") as? Int
} }
/** /**
:name: isLeftContainerOpened :name: isLeftContainerOpened
*/ */
public var isLeftContainerOpened: Bool { public var isLeftContainerOpened: Bool {
if let c = leftViewContainer { if let c = leftViewContainer {
...@@ -142,7 +86,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -142,7 +86,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
/** /**
:name: isUserInteractionEnabled :name: isUserInteractionEnabled
*/ */
public var isUserInteractionEnabled: Bool { public var isUserInteractionEnabled: Bool {
get { get {
...@@ -153,43 +97,48 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -153,43 +97,48 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
} }
/** //
:name: backdropViewContainer // :name: originalPosition
*/ //
public private(set) var backdropViewContainer: UIView? private var originalPosition: CGPoint!
/** /**
:name: mainViewContainer :name: backdropLayer
*/ */
public private(set) var mainViewContainer: UIView? public private(set) lazy var backdropLayer: MaterialLayer = MaterialLayer()
/** /**
:name: leftViewContainer :name: mainViewContainer
*/ */
public private(set) var leftViewContainer: UIView? public private(set) var mainViewContainer: MaterialView?
/** /**
:name: leftContainer :name: leftViewContainer
*/ */
public private(set) var leftContainer: SideNavigationViewContainer? public private(set) var leftViewContainer: MaterialView?
/** /**
:name: mainViewController :name: mainViewController
*/ */
public var mainViewController: UIViewController? public var mainViewController: UIViewController?
/** /**
:name: leftViewController :name: leftViewController
*/ */
public var leftViewController: UIViewController? public var leftViewController: UIViewController?
/** /**
:name: leftPanGesture :name: leftAnimation
*/
private var leftAnimation: CAAnimation?
/**
:name: leftPanGesture
*/ */
public var leftPanGesture: UIPanGestureRecognizer? public var leftPanGesture: UIPanGestureRecognizer?
/** /**
:name: leftTapGesture :name: leftTapGesture
*/ */
public var leftTapGesture: UITapGestureRecognizer? public var leftTapGesture: UITapGestureRecognizer?
...@@ -201,21 +150,21 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -201,21 +150,21 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
/** /**
:name: init :name: init
*/ */
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
/** /**
:name: init :name: init
*/ */
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
} }
/** /**
:name: init :name: init
*/ */
public convenience init(mainViewController: UIViewController) { public convenience init(mainViewController: UIViewController) {
self.init() self.init()
...@@ -224,7 +173,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -224,7 +173,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
/** /**
:name: init :name: init
*/ */
public convenience init(mainViewController: UIViewController, leftViewController: UIViewController) { public convenience init(mainViewController: UIViewController, leftViewController: UIViewController) {
self.init() self.init()
...@@ -252,87 +201,57 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -252,87 +201,57 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
} }
if nil != leftViewController { if nil != leftViewController {
prepareContainedViewController(&leftViewContainer, viewController: &leftViewController) // prepareContainedViewController(&leftViewContainer, viewController: &leftViewController)
} }
} }
/** /**
:name: toggleLeftViewContainer :name: toggleLeftViewContainer
*/ */
public func toggleLeftViewContainer(velocity: CGFloat = 0) { public func toggleLeftViewContainer(velocity: CGFloat = 0) {
isLeftContainerOpened ? closeLeftViewContainer(velocity) : openLeftViewContainer(velocity) openLeftViewContainer(velocity)
} }
/** /**
:name: openLeftViewContainer :name: openLeftViewContainer
*/ */
public func openLeftViewContainer(velocity: CGFloat = 0) { public func openLeftViewContainer(velocity: CGFloat = 0) {
if let vc = leftViewContainer { if let vc = leftViewContainer {
if let c = leftContainer {
prepareContainerToOpen(&leftViewController, viewContainer: &leftViewContainer, state: c.state) let w: CGFloat = vc.width
UIView.animateWithDuration(Double(0 == velocity ? options.animationDuration : fmax(0.1, fmin(1, Double(vc.frame.origin.x / velocity)))), let h: CGFloat = vc.height
delay: 0, let d: Double = Double(0 == velocity ? options.animationDuration : fmax(0.1, fmin(1, Double(vc.frame.origin.x / velocity))))
options: .CurveEaseInOut,
animations: { _ in vc.shadowDepth = .None
vc.frame.origin.x = 0
self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity) MaterialAnimation.animationWithDuration(d, animations: {
self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale) vc.position = CGPointMake(w / 2, h / 2)
} self.backdropLayer.opacity = Float(options.backdropOpacity)
) { _ in }) {
self.isUserInteractionEnabled = false self.isUserInteractionEnabled = false
} // vc.shadowDepth = .Depth2
c.state = .Opened
delegate?.sideNavDidOpenLeftViewContainer?(self, container: c)
}
}
}
/**
:name: closeLeftViewContainer
*/
public func closeLeftViewContainer(velocity: CGFloat = 0) {
if let vc = leftViewContainer {
if let c = leftContainer {
prepareContainerToClose(&leftViewController, state: c.state)
UIView.animateWithDuration(Double(0 == velocity ? options.animationDuration : fmax(0.1, fmin(1, fabs(vc.frame.origin.x - leftOriginX) / velocity))),
delay: 0,
options: .CurveEaseInOut,
animations: { _ in
vc.frame.origin.x = self.leftOriginX
self.backdropViewContainer?.layer.opacity = 0
self.mainViewContainer?.transform = CGAffineTransformMakeScale(1, 1)
}
) { _ in
self.removeShadow(&self.leftViewContainer)
self.isUserInteractionEnabled = true
}
c.state = .Closed
delegate?.sideNavDidCloseLeftViewContainer?(self, container: c)
} }
}
} // print(vc.frame)
// let a: CABasicAnimation = MaterialAnimation.position(CGPointMake(w / 2, h / 2), duration: d)
/** // a.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
:name: switchMainViewController // vc.animation(a)
*/ //
public func switchMainViewController(viewController: UIViewController, closeViewContainers: Bool) { ////
removeViewController(&mainViewController) // UIView.animateWithDuration(d,
mainViewController = viewController // delay: 0,
prepareContainedViewController(&mainViewContainer, viewController: &mainViewController) // options: .CurveEaseInOut,
if closeViewContainers { // animations: { _ in
closeLeftViewContainer() // vc.frame.origin.x = 0
} // self.backdropViewContainer?.layer.opacity = Float(options.backdropOpacity)
} // self.mainViewContainer?.transform = CGAffineTransformMakeScale(options.backdropScale, options.backdropScale)
// }
/** // ) { _ in
:name: switchLeftViewController // self.isUserInteractionEnabled = false
*/ // }
public func switchLeftViewController(viewController: UIViewController, closeLeftViewContainerViewContainer: Bool) { // c.state = .Opened
removeViewController(&leftViewController) // delegate?.sideNavDidOpenLeftViewContainer?(self, container: c)
leftViewController = viewController
prepareContainedViewController(&leftViewContainer, viewController: &leftViewController)
if closeLeftViewContainerViewContainer {
closeLeftViewContainer()
} }
} }
...@@ -361,8 +280,15 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -361,8 +280,15 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// :name: prepareLeftView // :name: prepareLeftView
// //
internal func prepareLeftView() { internal func prepareLeftView() {
prepareContainer(&leftContainer, viewContainer: &leftViewContainer, originX: leftOriginX, originY: 0, width: options.leftViewContainerWidth, height: view.bounds.size.height) prepareContainer(&leftViewContainer, originX: leftOriginX, originY: 0, width: options.leftViewContainerWidth, height: view.bounds.size.height)
prepareLeftGestures() prepareLeftGestures()
// leftViewContainer!.layer.speed = 0
let w: CGFloat = leftViewContainer!.width
let h: CGFloat = leftViewContainer!.height
// leftAnimation = MaterialAnimation.position(CGPointMake(w / 2, h / 2), duration: 1)
// leftViewContainer!.position = CGPointMake(-(w / 2), h / 2)
// leftViewContainer!.animation(leftAnimation!)
} }
// //
...@@ -398,36 +324,30 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -398,36 +324,30 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// //
// :name: handleLeftPanGesture // :name: handleLeftPanGesture
// //
internal func handleLeftPanGesture(gesture: UIPanGestureRecognizer) { internal func handleLeftPanGesture(recognizer: UIPanGestureRecognizer) {
if let vc = leftViewContainer { if let vc = leftViewContainer {
if let c = leftContainer { switch recognizer.state {
if .Began == gesture.state { case .Began:
addShadow(&leftViewContainer) originalPosition = vc.position
toggleStatusBar(true) toggleStatusBar(true)
c.state = isLeftContainerOpened ? .Opened : .Closed case .Changed:
c.point = gesture.locationInView(view) let translation: CGPoint = recognizer.translationInView(vc)
c.frame = vc.frame let w: CGFloat = leftViewContainer!.width
delegate?.sideNavDidBeginLeftPan?(self, container: c)
} else if .Changed == gesture.state { MaterialAnimation.animationDisabled({
c.point = gesture.translationInView(gesture.view!) vc.position.x = self.originalPosition.x + translation.x > (w / 2) ? (w / 2) : self.originalPosition.x + translation.x
let r = (vc.frame.origin.x - leftOriginX) / vc.frame.size.width self.backdropLayer.opacity = Float(vc.position.x / (w / 2)) / 2
let s: CGFloat = 1 - (1 - options.backdropScale) * r })
let x: CGFloat = c.frame.origin.x + c.point.x case .Ended:
vc.frame.origin.x = x < leftOriginX ? leftOriginX : x > 0 ? 0 : x self.isUserInteractionEnabled = false
backdropViewContainer?.layer.opacity = Float(r * options.backdropOpacity) // snap back
mainViewContainer?.transform = CGAffineTransformMakeScale(s, s) let a: CABasicAnimation = MaterialAnimation.position(CGPointMake(vc.width / 2, vc.height / 2), duration: 0.25)
delegate?.sideNavDidChangeLeftPan?(self, container: c) a.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
} else { vc.animation(a)
c.point = gesture.velocityInView(gesture.view)
let x: CGFloat = c.point.x >= 1000 || c.point.x <= -1000 ? c.point.x : 0 break
c.state = vc.frame.origin.x <= CGFloat(floor(leftOriginX)) + options.horizontalThreshold || c.point.x <= -1000 ? .Closed : .Opened
if .Closed == c.state { default:break
closeLeftViewContainer(x)
} else {
openLeftViewContainer(x)
}
delegate?.sideNavDidEndLeftPan?(self, container: c)
}
} }
} }
} }
...@@ -436,33 +356,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -436,33 +356,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// :name: handleLeftTapGesture // :name: handleLeftTapGesture
// //
internal func handleLeftTapGesture(gesture: UIPanGestureRecognizer) { internal func handleLeftTapGesture(gesture: UIPanGestureRecognizer) {
if let c = leftContainer {
delegate?.sideNavDidTapLeft?(self, container: c)
closeLeftViewContainer()
}
}
//
// :name: addShadow
//
private func addShadow(inout viewContainer: UIView?) {
if let vc = viewContainer {
vc.layer.shadowOffset = options.shadowOffset
vc.layer.shadowOpacity = options.shadowOpacity
vc.layer.shadowRadius = options.shadowRadius
vc.layer.shadowPath = UIBezierPath(rect: vc.bounds).CGPath
vc.layer.masksToBounds = false
}
}
//
// :name: removeShadow
//
private func removeShadow(inout viewContainer: UIView?) {
if let vc = viewContainer {
vc.layer.opacity = 1
vc.layer.masksToBounds = true
}
} }
// //
...@@ -510,7 +404,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -510,7 +404,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// //
// :name: isPointContainedWithinViewController // :name: isPointContainedWithinViewController
// //
private func isPointContainedWithinViewController(inout viewContainer: UIView?, point: CGPoint) -> Bool { private func isPointContainedWithinViewController(inout viewContainer: MaterialView?, point: CGPoint) -> Bool {
if let vc = viewContainer { if let vc = viewContainer {
return CGRectContainsPoint(vc.frame, point) return CGRectContainsPoint(vc.frame, point)
} }
...@@ -521,7 +415,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -521,7 +415,7 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// :name: prepareMainContainer // :name: prepareMainContainer
// //
private func prepareMainContainer() { private func prepareMainContainer() {
mainViewContainer = UIView(frame: view.bounds) mainViewContainer = MaterialView(frame: view.bounds)
mainViewContainer!.backgroundColor = MaterialColor.clear mainViewContainer!.backgroundColor = MaterialColor.clear
mainViewContainer!.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] mainViewContainer!.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
view.addSubview(mainViewContainer!) view.addSubview(mainViewContainer!)
...@@ -531,11 +425,10 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -531,11 +425,10 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// :name: prepareBackdropContainer // :name: prepareBackdropContainer
// //
private func prepareBackdropContainer() { private func prepareBackdropContainer() {
backdropViewContainer = UIView(frame: view.bounds) backdropLayer.frame = view.bounds
backdropViewContainer!.backgroundColor = options.backdropBackgroundColor backdropLayer.backgroundColor = options.backdropBackgroundColor.CGColor
backdropViewContainer!.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] backdropLayer.opacity = 0
backdropViewContainer!.layer.opacity = 0 view.layer.addSublayer(backdropLayer)
view.addSubview(backdropViewContainer!)
} }
// //
...@@ -549,33 +442,17 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer ...@@ -549,33 +442,17 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
// //
// :name: prepareContainer // :name: prepareContainer
// //
private func prepareContainer(inout container: SideNavigationViewContainer?, inout viewContainer: UIView?, originX: CGFloat, originY: CGFloat, width: CGFloat, height: CGFloat) { private func prepareContainer(inout viewContainer: MaterialView?, originX: CGFloat, originY: CGFloat, width: CGFloat, height: CGFloat) {
container = SideNavigationViewContainer(state: .Closed, point: CGPointZero, frame: CGRectZero) viewContainer = MaterialView(frame: CGRectMake(originX, originY, width, height))
viewContainer = UIView(frame: CGRectMake(originX, originY, width, height)) viewContainer!.backgroundColor = MaterialColor.red.base
viewContainer!.backgroundColor = MaterialColor.clear
viewContainer!.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] viewContainer!.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
view.addSubview(viewContainer!) view.addSubview(viewContainer!)
} }
// //
// :name: prepareContainerToOpen
//
private func prepareContainerToOpen(inout viewController: UIViewController?, inout viewContainer: UIView?, state: SideNavigationViewState) {
addShadow(&viewContainer)
toggleStatusBar(true)
}
//
// :name: prepareContainerToClose
//
private func prepareContainerToClose(inout viewController: UIViewController?, state: SideNavigationViewState) {
toggleStatusBar()
}
//
// :name: prepareContainedViewController // :name: prepareContainedViewController
// //
private func prepareContainedViewController(inout viewContainer: UIView?, inout viewController: UIViewController?) { private func prepareContainedViewController(inout viewContainer: MaterialView?, inout viewController: UIViewController?) {
if let vc = viewController { if let vc = viewController {
if let c = viewContainer { if let c = viewContainer {
addChildViewController(vc) addChildViewController(vc)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment