Skip to content

Commit

Permalink
GIB-26 | custom presentation controller added (#27)
Browse files Browse the repository at this point in the history
* GIB-26 | custom presentation controller added

* GIB-26 | TODO comment added for transition variation support
  • Loading branch information
rajatgupta26 authored Dec 5, 2018
1 parent 2647080 commit 72916e6
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 53 deletions.
28 changes: 2 additions & 26 deletions ContentSheet/Classes/ContentSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,6 @@ public class ContentSheet: UIViewController {
return imageView
} ()

private lazy var _overlay: UIView = {
let overlay: UIView = UIView(frame: self.view.bounds)
overlay.contentMode = .scaleAspectFill
overlay.backgroundColor = UIColor(white: 0.0, alpha: 0.7)
overlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]

return overlay
} ()

private var _blurView: UIVisualEffectView {
get {
let effect: UIBlurEffect = UIBlurEffect(style: blurStyle)
let effectView = UIVisualEffectView(effect: effect)
effectView.frame = self.view.bounds
effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

return effectView
}
}

//background image
public var backgroundImage: UIImage? {
didSet {
Expand All @@ -170,17 +150,12 @@ public class ContentSheet: UIViewController {
let view = backgroundView != nil ? backgroundView! : _defaultBackground
view.frame = self.view.bounds

if blurBackground {
view.addSubview(_blurView)
} else {
view.addSubview(_overlay)
}
return view
}
}

//Settings
public var blurBackground: Bool = true
public var blurBackground: Bool = false
public var blurStyle: UIBlurEffectStyle = .dark
public var dismissOnTouchOutside: Bool = true
public var handleKeyboard: Bool = false {
Expand Down Expand Up @@ -304,6 +279,7 @@ public class ContentSheet: UIViewController {
public required init(content: ContentSheetContentProtocol) {
_content = content
super.init(nibName: nil, bundle: nil)
self.modalPresentationStyle = .custom
}

//MARK: View lifecycle
Expand Down
128 changes: 108 additions & 20 deletions ContentSheet/Classes/ContentSheetTransitionDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,22 @@ public class ContentSheetAnimator: NSObject, UIViewControllerAnimatedTransitioni
}

public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

let fromViewController: UIViewController? = transitionContext.viewController(forKey: .from)
let toViewController: UIViewController? = transitionContext.viewController(forKey: .to)

let fromView: UIView? = transitionContext.view(forKey: .from)
let toView: UIView? = transitionContext.view(forKey: .to)

if let fromView = fromView, let toView = toView {
let fromViewFrame: CGRect = fromViewController != nil ? transitionContext.initialFrame(for: fromViewController!) : UIScreen.main.bounds
let toViewFrame: CGRect = toViewController != nil ? transitionContext.finalFrame(for: toViewController!) : UIScreen.main.bounds
let fromViewFrame: CGRect = fromViewController != nil ? transitionContext.initialFrame(for: fromViewController!) : UIScreen.main.bounds
let toViewFrame: CGRect = toViewController != nil ? transitionContext.finalFrame(for: toViewController!) : UIScreen.main.bounds

if presenting {

if presenting {
if let toView = toView {

toView.frame = toViewFrame
toView.alpha = 0.0
fromView.frame = fromViewFrame

transitionContext.containerView.addSubview(toView)

Expand All @@ -74,13 +73,13 @@ public class ContentSheetAnimator: NSObject, UIViewControllerAnimatedTransitioni
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})

} else {
}
} else {

if let fromView = fromView {

toView.frame = toViewFrame
fromView.frame = fromViewFrame

transitionContext.containerView.insertSubview(toView, belowSubview: fromView)

UIView.animate(withDuration: self.duration,
delay: 0.0,
usingSpringWithDamping: 0.75,
Expand All @@ -92,7 +91,6 @@ public class ContentSheetAnimator: NSObject, UIViewControllerAnimatedTransitioni
completion: { (finished) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})

}
}
}
Expand All @@ -114,28 +112,118 @@ public class ContentSheetTransitionDelegate: NSObject, UIViewControllerTransitio
}

public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {

if let sheet = presented as? ContentSheet {
if sheet.backgroundView == nil && sheet.backgroundImage == nil {
sheet.backgroundView = presenting.view.snapshotView(afterScreenUpdates: false)
}
}

let animator: ContentSheetAnimator = ContentSheetAnimator()
animator.duration = duration
return animator
}

public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator: ContentSheetAnimator = ContentSheetAnimator()
animator.duration = duration
animator.presenting = false
return animator
}

public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return ContentSheetPresentationController(presentedViewController: presented, presenting: presenting)
}
}


/*
TODO: Add support for different kind of presentation transitions.
First variation could be to just add direction of sliding in as an option.
*/
public class ContentSheetPresentationController: UIPresentationController {

public override func presentationTransitionWillBegin() {
if let sheet = self.presentedViewController as? ContentSheet {
_overlay = sheet.blurBackground ? _blurView(sheet.blurStyle) : _dimmingView()
_overlay!.alpha = 0.0
self.containerView?.insertSubview(_overlay!, at: 0)

guard let coordinator = presentedViewController.transitionCoordinator else {
_overlay!.alpha = 1.0
return
}

coordinator.animate(alongsideTransition: { _ in
self._overlay!.alpha = 1.0
})
}
}

public override func presentationTransitionDidEnd(_ completed: Bool) {
if !completed {
self._overlay?.removeFromSuperview()
}
}

public override func dismissalTransitionWillBegin() {
if let sheet = self.presentedViewController as? ContentSheet, !sheet.blurBackground {
guard let coordinator = presentedViewController.transitionCoordinator else {
_overlay!.alpha = 0.0
return
}

coordinator.animate(alongsideTransition: { _ in
self._overlay!.alpha = 0.0
})
}
}

public override func dismissalTransitionDidEnd(_ completed: Bool) {
if completed {
self._overlay?.removeFromSuperview()
} else {
self._overlay?.alpha = 1.0
}
}

override public func containerViewWillLayoutSubviews() {
presentedView?.frame = frameOfPresentedViewInContainerView
}

override public func size(forChildContentContainer container: UIContentContainer,
withParentContainerSize parentSize: CGSize) -> CGSize {
return parentSize
}

override public var frameOfPresentedViewInContainerView: CGRect {
var frame: CGRect = .zero
frame.size = size(forChildContentContainer: presentedViewController,
withParentContainerSize: containerView!.bounds.size)
return frame
}


private var _overlay: UIView?

private func _dimmingView() -> UIView {
let dimmingView: UIView = UIView(frame: self.containerView?.bounds ?? self.presentingViewController.view.bounds)
dimmingView.contentMode = .scaleAspectFill
dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
dimmingView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

let recognizer = UITapGestureRecognizer(target: self, action: #selector(_handleTap(recognizer:)))
dimmingView.addGestureRecognizer(recognizer)

return dimmingView
}

private func _blurView(_ style: UIBlurEffectStyle) -> UIVisualEffectView {
let effect: UIBlurEffect = UIBlurEffect(style: style)
let effectView = UIVisualEffectView(effect: effect)
effectView.frame = self.containerView?.bounds ?? self.presentingViewController.view.bounds
effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

return effectView
}

private dynamic func _handleTap(recognizer: UITapGestureRecognizer) {
presentingViewController.dismiss(animated: true)
}
}



Expand Down
7 changes: 3 additions & 4 deletions Example/FKWidgetSheet/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand Down Expand Up @@ -91,6 +90,6 @@
</scene>
</scenes>
<resources>
<image name="1" width="16" height="16"/>
<image name="1" width="213" height="378"/>
</resources>
</document>
52 changes: 50 additions & 2 deletions Example/FKWidgetSheet/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ViewController: UIViewController {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
UINavigationBar.appearance().barTintColor = UIColor.purple

self._craeteShapeLayer()
}

override func didReceiveMemoryWarning() {
Expand All @@ -37,6 +39,49 @@ class ViewController: UIViewController {

private var canPresent = false
var a: SecondViewController?
private var iconLayer: CAShapeLayer!

private func _craeteShapeLayer() {

let iconPath = UIBezierPath()
iconPath.move(to: CGPoint(x: 26.5, y: 0.5))
iconPath.addLine(to: CGPoint(x: 20.5, y: 0.5))
iconPath.addLine(to: CGPoint(x: 16.5, y: 5.5))
iconPath.addLine(to: CGPoint(x: 13.5, y: 25.5))
iconPath.addLine(to: CGPoint(x: 10.5, y: 45.5))
iconPath.addLine(to: CGPoint(x: 6.5, y: 50.5))
iconPath.addLine(to: CGPoint(x: 0.5, y: 50.5))
iconPath.move(to: CGPoint(x: 0.5, y: 25.5))
iconPath.addLine(to: CGPoint(x: 25.5, y: 25.5))

iconLayer = CAShapeLayer()
iconLayer.path = iconPath.cgPath
iconLayer.strokeColor = UIColor.white.cgColor
iconLayer.fillColor = UIColor.clear.cgColor
iconLayer.lineWidth = 5

var iconLayerFrame = self.view.bounds
iconLayerFrame.size.height = 60
iconLayerFrame.size.width = 26
iconLayerFrame.origin.x = (self.view.bounds.width - iconLayerFrame.size.width)/2
iconLayerFrame.origin.y = 88

iconLayer.frame = iconLayerFrame
iconLayer.transform = CATransform3DScale(CATransform3DIdentity, 2.5, 2.5, 1)

self.view.layer.addSublayer(iconLayer)
}

private func _animateIcon() {
let pathAnimation = CABasicAnimation(keyPath: "strokeStart")
pathAnimation.duration = 1.5
pathAnimation.fromValue = -2.0
pathAnimation.toValue = 1.0
pathAnimation.autoreverses = true
pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
pathAnimation.repeatCount = Float.greatestFiniteMagnitude
iconLayer.add(pathAnimation, forKey: "strokeStartAnimation")
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Expand All @@ -46,12 +91,15 @@ class ViewController: UIViewController {
a?.willMove(toParentViewController: self)
a?.view.backgroundColor = UIColor.yellow
self.addChildViewController(a!)
var frame = self.view.bounds.insetBy(dx: 25, dy: 100)
frame.origin.y -= 50
var frame = self.view.bounds.insetBy(dx: 25, dy: 0)
frame.size.height = 88
frame.origin.y = self.view.bounds.midY - 44
a?.view.frame = frame
self.view.addSubview(a!.view)
a?.didMove(toParentViewController: self)

self.view.backgroundColor = UIColor.purple
self._animateIcon()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Use these properties of content sheet to customize behaviour

```swift
public var showDefaultHeader: Bool = true
public var blurBackground: Bool = true
public var blurBackground: Bool = false
public var blurStyle: UIBlurEffectStyle = .dark
public var dismissOnTouchOutside: Bool = true
public var backgroundImage: UIImage?
Expand Down

0 comments on commit 72916e6

Please sign in to comment.