I created a custom UIPresentationController and want the top sixth of the screen to contain a dismissButton and dimmingView to fade in and out on present and dismiss, respectively. However, because the dismissButton is outside the presentedView, it is not tappable. Is there any solution to this?
Note: I know I can add the subview to the presentedView and then move the dismissButton outside of the view, but if I do this, the button presents in the same way that the rest of the controller does, instead of fading in like I want it to (not sliding up).
@available(iOS 13.0, *)
open class CUICFiveSixthPopUpTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
let dimmingColor: UIColor!
public init(dimmingColor: UIColor) {
self.dimmingColor = dimmingColor
super.init()
}
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return CUICFiveSixthPopUpPresentationController(presentedViewController: presented, presenting: presenting, dimmingColor: dimmingColor)
}
}
@available(iOS 13.0, *)
open class CUICFiveSixthPopUpPresentationController: UIPresentationController {
open override var frameOfPresentedViewInContainerView: CGRect {
let bounds = presentingViewController.view.bounds
let size = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height*5/6)
let origin = CGPoint(x: bounds.midX - size.width / 2, y: UIScreen.main.bounds.height - size.height)
return CGRect(origin: origin, size: size)
}
public init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, dimmingColor: UIColor) {
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
presentedView?.autoresizingMask = [
.flexibleTopMargin,
.flexibleBottomMargin,
.flexibleLeftMargin,
.flexibleRightMargin
]
presentedViewController.view.layer.cornerRadius = viewRadius
presentedViewController.view.clipsToBounds = true
dimmingView.backgroundColor = dimmingColor
dismissButton.backgroundColor = dimmingColor.lighter()
presentedView?.translatesAutoresizingMaskIntoConstraints = true
}
let iconSize: CGFloat = 40
let viewRadius: CGFloat = 35
let dimmingView: UIView = {
let dimmingView = UIView(frame: .zero)
dimmingView.translatesAutoresizingMaskIntoConstraints = false
return dimmingView
}()
let dismissButton: UIButton = {
let dismissButton = UIButton(frame: .zero)
dismissButton.tintColor = .white
dismissButton.alpha = 0.8
dismissButton.setImage(.close, for: .normal)
dismissButton.translatesAutoresizingMaskIntoConstraints = false
return dismissButton
}()
@objc private func dimmingViewTapped(_ sender: UITapGestureRecognizer) {
let point = sender.location(in: presentingViewController.view!)
if dismissButton.frame.contains(point) {
presentedViewController.dismiss(animated: true)
}
}
open override func presentationTransitionWillBegin() {
super.presentationTransitionWillBegin()
let superview = presentingViewController.view!
let presentedView = presentedView!
superview.addSubview(dimmingView)
superview.addSubview(dismissButton)
NSLayoutConstraint.activate([
dimmingView.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
dimmingView.trailingAnchor.constraint(equalTo: superview.trailingAnchor),
dimmingView.bottomAnchor.constraint(equalTo: superview.bottomAnchor),
dimmingView.topAnchor.constraint(equalTo: superview.topAnchor),
dismissButton.topAnchor.constraint(equalTo: superview.topAnchor, constant: .marginFromTopOfScreen),
dismissButton.leftAnchor.constraint(equalTo: superview.leftAnchor, constant: .marginLeft),
dismissButton.heightAnchor.constraint(equalToConstant: iconSize),
dismissButton.widthAnchor.constraint(equalToConstant: iconSize),
])
dismissButton.layer.cornerRadius = iconSize/2
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dimmingViewTapped(_:)))
dimmingView.addGestureRecognizer(tapGesture)
dimmingView.alpha = 0
presentingViewController.transitionCoordinator?.animate(alongsideTransition: { [weak self] _ in
self?.dimmingView.alpha = 1
}, completion: nil)
}
open override func dismissalTransitionWillBegin() {
super.dismissalTransitionWillBegin()
presentingViewController.transitionCoordinator?.animate(alongsideTransition: { _ in
self.dimmingView.alpha = 0
}, completion: { _ in
self.dimmingView.removeFromSuperview()
})
}
}