Skip to content

Instantly share code, notes, and snippets.

@alfredcc
Created August 19, 2020 10:07
Show Gist options
  • Save alfredcc/810798bdb5fce5e3e20684a27b713e23 to your computer and use it in GitHub Desktop.
Save alfredcc/810798bdb5fce5e3e20684a27b713e23 to your computer and use it in GitHub Desktop.
MyPresentationController
import UIKit
import RxSwift
class MyPresentationController: UIPresentationController {
/** To save keyboard animation duration. */
private var _animationDuration : TimeInterval = 0.25
/** To mimic the keyboard animation */
private var _animationCurve = UIView.AnimationOptions.curveEaseOut
private let disposeBag = DisposeBag()
/** height of content */
var controllerHeight: CGFloat = 200 + UIWindow.safeAreaInsetBottom
lazy var dimmingView: UIView = {
let view = UIView()
if let frame = self.containerView?.bounds {
view.frame = frame
}
view.backgroundColor = UIColor.black.withAlphaComponent(0.6)
view.rx.tapGesture().when(.recognized)
.subscribe(onNext: { [weak self](_) in
self?.presentedViewController.dismiss(animated: true, completion: nil)
}).disposed(by: disposeBag)
return view
}()
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
}
override func presentationTransitionWillBegin() {
containerView?.backgroundColor = .clear
dimmingView.alpha = 0
containerView?.addSubview(dimmingView)
//Used UIViewAnimationOptionBeginFromCurrentState to minimize strange animations.
UIView.animate(withDuration: _animationDuration, delay: 0,
options: UIView.AnimationOptions.beginFromCurrentState.union(_animationCurve),
animations: { () -> Void in
self.dimmingView.alpha = 1
}, completion: nil)
}
override func dismissalTransitionWillBegin() {
if let frame = self.containerView?.bounds {
self.dimmingView.frame = frame
}
//Used UIViewAnimationOptionBeginFromCurrentState to minimize strange animations.
UIView.animate(withDuration: _animationDuration, delay: 0,
options: UIView.AnimationOptions.beginFromCurrentState.union(_animationCurve),
animations: { () -> Void in
self.dimmingView.alpha = 0
}, completion: nil)
}
override func dismissalTransitionDidEnd(_ completed: Bool) {
self.dimmingView.removeFromSuperview()
}
override var frameOfPresentedViewInContainerView: CGRect {
return CGRect(x: 0,
y: UIScreen.height - controllerHeight,
width: UIScreen.width,
height: controllerHeight)
}
override var presentedView : UIView? {
let presentedView = super.presentedView
// HACK: This is a workaround for the bug described in: http://openradar.appspot.com/18005149
// UIKit changes the frame of the `presentedView` outside of our control. We can change that frame in
// `containerViewWillLayoutSubviews()` but it's too late in the process - if we do that it's visible that
// the frame changes without an animation during dismissal.
presentedView?.frame = frameOfPresentedViewInContainerView
return presentedView
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment